diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 317ee67e0c055..7d83c0851eb8c 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -90,10 +90,13 @@ disabled: - x-pack/test_serverless/functional/test_suites/common/config.ts - x-pack/test_serverless/functional/test_suites/observability/config.ts - x-pack/test_serverless/functional/test_suites/observability/config.feature_flags.ts + - x-pack/test_serverless/functional/test_suites/observability/config.examples.ts - x-pack/test_serverless/functional/test_suites/search/config.ts - x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts + - x-pack/test_serverless/functional/test_suites/search/config.examples.ts - x-pack/test_serverless/functional/test_suites/security/config.ts - x-pack/test_serverless/functional/test_suites/security/config.feature_flags.ts + - x-pack/test_serverless/functional/test_suites/security/config.examples.ts defaultQueue: 'n2-4-spot' enabled: @@ -279,7 +282,6 @@ enabled: - x-pack/test/functional/apps/data_views/config.ts - x-pack/test/functional/apps/dev_tools/config.ts - x-pack/test/functional/apps/discover/config.ts - - x-pack/test/functional/apps/discover_log_explorer/config.ts - x-pack/test/functional/apps/graph/config.ts - x-pack/test/functional/apps/grok_debugger/config.ts - x-pack/test/functional/apps/home/config.ts @@ -313,6 +315,7 @@ enabled: - x-pack/test/functional/apps/ml/short_tests/config.ts - x-pack/test/functional/apps/ml/stack_management_jobs/config.ts - x-pack/test/functional/apps/monitoring/config.ts + - x-pack/test/functional/apps/observability_log_explorer/config.ts - x-pack/test/functional/apps/remote_clusters/config.ts - x-pack/test/functional/apps/reporting_management/config.ts - x-pack/test/functional/apps/rollup_job/config.ts @@ -419,6 +422,7 @@ enabled: - x-pack/performance/journeys/ecommerce_dashboard_saved_search_only.ts - x-pack/performance/journeys/ecommerce_dashboard_tsvb_gauge_only.ts - x-pack/performance/journeys/dashboard_listing_page.ts + - x-pack/performance/journeys/tags_listing_page.ts - x-pack/performance/journeys/cloud_security_dashboard.ts - x-pack/performance/journeys/apm_service_inventory.ts - x-pack/test/custom_branding/config.ts diff --git a/.buildkite/pipelines/on_merge_unsupported_ftrs.yml b/.buildkite/pipelines/on_merge_unsupported_ftrs.yml index 1d141a9755247..30e7929fd6e19 100644 --- a/.buildkite/pipelines/on_merge_unsupported_ftrs.yml +++ b/.buildkite/pipelines/on_merge_unsupported_ftrs.yml @@ -55,7 +55,7 @@ steps: queue: n2-4-spot depends_on: build timeout_in_minutes: 120 - parallelism: 6 + parallelism: 14 retry: automatic: - exit_status: '*' diff --git a/.buildkite/pipelines/pipeline.kibana-serverless-release.yaml b/.buildkite/pipelines/pipeline.kibana-serverless-release.yaml new file mode 100644 index 0000000000000..6bceff183662a --- /dev/null +++ b/.buildkite/pipelines/pipeline.kibana-serverless-release.yaml @@ -0,0 +1,9 @@ +steps: + - label: ":releasethekraken: Release kibana" + # https://regex101.com/r/tY52jo/1 + if: build.tag =~ /^deploy@\d+\$/ + trigger: gpctl-promote + build: + env: + SERVICE_COMMIT_HASH: "${BUILDKITE_COMMIT:0:12}" + REMOTE_SERVICE_CONFIG: https://raw.githubusercontent.com/elastic/serverless-gitops/main/gen/gpctl/kibana/config.yaml diff --git a/.buildkite/pipelines/pull_request/base.yml b/.buildkite/pipelines/pull_request/base.yml index bb96479a2b83a..7a4291fab7003 100644 --- a/.buildkite/pipelines/pull_request/base.yml +++ b/.buildkite/pipelines/pull_request/base.yml @@ -69,6 +69,19 @@ steps: - exit_status: '-1' limit: 3 + - command: SERVERLESS_ENVIRONMENT=observability.examples .buildkite/scripts/steps/functional/serverless_ftr.sh + label: 'Serverless Observability Examples Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 40 + soft_fail: + - exit_status: 10 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - command: SERVERLESS_ENVIRONMENT=search .buildkite/scripts/steps/functional/serverless_ftr.sh label: 'Serverless Search Tests' agents: @@ -82,6 +95,19 @@ steps: - exit_status: '-1' limit: 3 + - command: SERVERLESS_ENVIRONMENT=search.examples .buildkite/scripts/steps/functional/serverless_ftr.sh + label: 'Serverless Search Examples Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 40 + soft_fail: + - exit_status: 10 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - command: SERVERLESS_ENVIRONMENT=security .buildkite/scripts/steps/functional/serverless_ftr.sh label: 'Serverless Security Tests' agents: @@ -95,27 +121,26 @@ steps: - exit_status: '-1' limit: 3 - - command: .buildkite/scripts/steps/functional/security_serverless.sh - label: 'Serverless Security Cypress Tests' + - command: SERVERLESS_ENVIRONMENT=security.examples .buildkite/scripts/steps/functional/serverless_ftr.sh + label: 'Serverless Security Examples Tests' agents: queue: n2-4-spot depends_on: build timeout_in_minutes: 40 - parallelism: 16 - soft_fail: true + soft_fail: + - exit_status: 10 retry: automatic: - - exit_status: '*' - limit: 1 - artifact_paths: - - "target/kibana-security-solution/**/*" + - exit_status: '-1' + limit: 3 - - command: .buildkite/scripts/steps/functional/security_serverless_defend_workflows.sh - label: 'Serverless Security Defend Workflows Cypress Tests' + - command: .buildkite/scripts/steps/functional/security_serverless.sh + label: 'Serverless Security Cypress Tests' agents: queue: n2-4-spot depends_on: build timeout_in_minutes: 40 + parallelism: 16 soft_fail: true retry: automatic: @@ -124,6 +149,21 @@ steps: artifact_paths: - "target/kibana-security-solution/**/*" + # status_exception: Native role management is not enabled in this Elasticsearch instance + # - command: .buildkite/scripts/steps/functional/security_serverless_defend_workflows.sh + # label: 'Serverless Security Defend Workflows Cypress Tests' + # agents: + # queue: n2-4-spot + # depends_on: build + # timeout_in_minutes: 40 + # soft_fail: true + # retry: + # automatic: + # - exit_status: '*' + # limit: 1 + # artifact_paths: + # - "target/kibana-security-solution/**/*" + - command: .buildkite/scripts/steps/functional/security_serverless_investigations.sh label: 'Serverless Security Investigations Cypress Tests' agents: diff --git a/.buildkite/pipelines/pull_request/defend_workflows.yml b/.buildkite/pipelines/pull_request/defend_workflows.yml index 02f9239a8e6a2..3a50e3ece206e 100644 --- a/.buildkite/pipelines/pull_request/defend_workflows.yml +++ b/.buildkite/pipelines/pull_request/defend_workflows.yml @@ -4,7 +4,7 @@ steps: agents: queue: n2-4-spot depends_on: build - timeout_in_minutes: 120 + timeout_in_minutes: 60 parallelism: 2 retry: automatic: @@ -16,9 +16,9 @@ steps: - command: .buildkite/scripts/steps/functional/defend_workflows_vagrant.sh label: 'Defend Workflows Endpoint Cypress Tests' agents: - queue: n2-16-virt + queue: n2-4-virt depends_on: build - timeout_in_minutes: 120 + timeout_in_minutes: 60 parallelism: 6 retry: automatic: diff --git a/.buildkite/pipelines/pull_request/osquery_cypress.yml b/.buildkite/pipelines/pull_request/osquery_cypress.yml index 8e8ace5ff7975..c56d94524f60d 100644 --- a/.buildkite/pipelines/pull_request/osquery_cypress.yml +++ b/.buildkite/pipelines/pull_request/osquery_cypress.yml @@ -20,19 +20,22 @@ steps: depends_on: build timeout_in_minutes: 50 soft_fail: true - artifact_paths: - - "target/kibana-osquery/**/*" - - - command: .buildkite/scripts/steps/functional/security_serverless_osquery.sh - label: 'Serverless Osquery Cypress Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 50 - parallelism: 6 retry: - automatic: - - exit_status: '*' - limit: 1 + automatic: false artifact_paths: - "target/kibana-osquery/**/*" + + # Error: self-signed certificate in certificate chain + # - command: .buildkite/scripts/steps/functional/security_serverless_osquery.sh + # label: 'Serverless Osquery Cypress Tests' + # agents: + # queue: n2-4-spot + # depends_on: build + # timeout_in_minutes: 50 + # parallelism: 6 + # retry: + # automatic: + # - exit_status: '*' + # limit: 1 + # artifact_paths: + # - "target/kibana-osquery/**/*" diff --git a/.buildkite/pipelines/pull_request/security_solution.yml b/.buildkite/pipelines/pull_request/security_solution.yml index 4a4938ac86b01..58b416548ec5f 100644 --- a/.buildkite/pipelines/pull_request/security_solution.yml +++ b/.buildkite/pipelines/pull_request/security_solution.yml @@ -11,7 +11,7 @@ steps: - exit_status: '*' limit: 1 artifact_paths: - - "target/kibana-security-solution/**/*" + - 'target/kibana-security-solution/**/*' - command: .buildkite/scripts/steps/functional/security_solution_explore.sh label: 'Explore - Security Solution Cypress Tests' @@ -19,13 +19,13 @@ steps: queue: n2-4-spot depends_on: build timeout_in_minutes: 60 - parallelism: 2 + parallelism: 4 retry: automatic: - exit_status: '*' limit: 1 artifact_paths: - - "target/kibana-security-solution/**/*" + - 'target/kibana-security-solution/**/*' - command: .buildkite/scripts/steps/functional/security_solution_investigations.sh label: 'Investigations - Security Solution Cypress Tests' @@ -39,7 +39,7 @@ steps: - exit_status: '*' limit: 1 artifact_paths: - - "target/kibana-security-solution/**/*" + - 'target/kibana-security-solution/**/*' - command: .buildkite/scripts/steps/functional/security_solution_burn.sh label: 'Security Solution Cypress tests, burning changed specs' @@ -48,6 +48,15 @@ steps: depends_on: build timeout_in_minutes: 120 parallelism: 1 + retry: + automatic: false soft_fail: true artifact_paths: - - "target/kibana-security-solution/**/*" + - 'target/kibana-security-solution/**/*' + + - command: .buildkite/scripts/steps/code_generation/security_solution_codegen.sh + label: 'Security Solution OpenAPI codegen' + agents: + queue: n2-2-spot + timeout_in_minutes: 60 + parallelism: 1 diff --git a/.buildkite/pipelines/serverless.yml b/.buildkite/pipelines/serverless.yml index 2d6e304592fb1..be9816545e2bf 100644 --- a/.buildkite/pipelines/serverless.yml +++ b/.buildkite/pipelines/serverless.yml @@ -34,6 +34,19 @@ steps: - exit_status: '*' limit: 1 + - command: SERVERLESS_ENVIRONMENT=observability.examples .buildkite/scripts/steps/functional/serverless_ftr.sh + label: 'Serverless Observability Examples Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 40 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + - command: SERVERLESS_ENVIRONMENT=search .buildkite/scripts/steps/functional/serverless_ftr.sh label: 'Serverless Search Tests' agents: @@ -47,6 +60,19 @@ steps: - exit_status: '*' limit: 1 + - command: SERVERLESS_ENVIRONMENT=search.examples .buildkite/scripts/steps/functional/serverless_ftr.sh + label: 'Serverless Search Examples Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 40 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + - command: SERVERLESS_ENVIRONMENT=security .buildkite/scripts/steps/functional/serverless_ftr.sh label: 'Serverless Security Tests' agents: @@ -60,6 +86,19 @@ steps: - exit_status: '*' limit: 1 + - command: SERVERLESS_ENVIRONMENT=security.examples .buildkite/scripts/steps/functional/serverless_ftr.sh + label: 'Serverless Security Examples Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 40 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + - command: .buildkite/scripts/steps/functional/security_serverless.sh label: 'Serverless Security Cypress Tests' agents: @@ -75,7 +114,7 @@ steps: - "target/kibana-security-serverless/**/*" - command: .buildkite/scripts/steps/functional/security_serverless_explore.sh - label: 'Explore - Security Solution Cypress Tests' + label: 'Serverless Explore - Security Solution Cypress Tests' agents: queue: n2-4-spot depends_on: build @@ -89,7 +128,7 @@ steps: - "target/kibana-security-serverless/**/*" - command: .buildkite/scripts/steps/functional/security_serverless_investigations.sh - label: 'Investigations - Security Solution Cypress Tests' + label: 'Serverless Investigations - Security Solution Cypress Tests' agents: queue: n2-4-spot depends_on: build diff --git a/.buildkite/scripts/common/util.sh b/.buildkite/scripts/common/util.sh index e22a807fc1830..eca5fe352abcf 100755 --- a/.buildkite/scripts/common/util.sh +++ b/.buildkite/scripts/common/util.sh @@ -31,7 +31,7 @@ check_for_changed_files() { SHOULD_AUTO_COMMIT_CHANGES="${2:-}" CUSTOM_FIX_MESSAGE="${3:-}" - GIT_CHANGES="$(git ls-files --modified -- . ':!:.bazelrc')" + GIT_CHANGES="$(git status --porcelain -- . ':!:.bazelrc')" if [ "$GIT_CHANGES" ]; then if ! is_auto_commit_disabled && [[ "$SHOULD_AUTO_COMMIT_CHANGES" == "true" && "${BUILDKITE_PULL_REQUEST:-}" ]]; then @@ -54,7 +54,7 @@ check_for_changed_files() { git config --global user.name kibanamachine git config --global user.email '42973632+kibanamachine@users.noreply.github.com' gh pr checkout "${BUILDKITE_PULL_REQUEST}" - git add -u -- . ':!.bazelrc' + git add -A -- . ':!.bazelrc' git commit -m "$NEW_COMMIT_MESSAGE" git push diff --git a/.buildkite/scripts/lifecycle/pre_command.sh b/.buildkite/scripts/lifecycle/pre_command.sh index b945f08d1dfd9..cf31fc95bcb5a 100755 --- a/.buildkite/scripts/lifecycle/pre_command.sh +++ b/.buildkite/scripts/lifecycle/pre_command.sh @@ -2,6 +2,11 @@ set -euo pipefail +if [[ "$BUILDKITE_COMMAND" =~ ^"buildkite-agent pipeline upload" ]]; then + echo "Skipped pre-command when running the Upload pipeline" + exit 0 +fi + source .buildkite/scripts/common/util.sh echo '--- Setup environment vars' diff --git a/.buildkite/scripts/steps/artifacts/docker_image.sh b/.buildkite/scripts/steps/artifacts/docker_image.sh index 3743aedfdc655..6a0c23384ef65 100755 --- a/.buildkite/scripts/steps/artifacts/docker_image.sh +++ b/.buildkite/scripts/steps/artifacts/docker_image.sh @@ -98,12 +98,14 @@ steps: - label: ":argo: Update kibana image tag for kibana-controller using gpctl" async: true branches: main - trigger: gpctl-promote + trigger: gpctl-promote-with-e2e-tests build: env: SERVICE_COMMIT_HASH: "$GIT_ABBREV_COMMIT" - REMOTE_SERVICE_CONFIG: https://raw.githubusercontent.com/elastic/serverless-gitops/main/gen/gpctl/kibana/config.yaml - + SERVICE: kibana-controller + NAMESPACE: kibana-ci + IMAGE_NAME: kibana-serverless + REMOTE_SERVICE_CONFIG: https://raw.githubusercontent.com/elastic/serverless-gitops/main/gen/gpctl/kibana/dev.yaml EOF else diff --git a/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh b/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh new file mode 100755 index 0000000000000..f6d31f3e94bbc --- /dev/null +++ b/.buildkite/scripts/steps/code_generation/security_solution_codegen.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/common/util.sh + +.buildkite/scripts/bootstrap.sh + +echo --- Security Solution OpenAPI Code Generation + +(cd x-pack/plugins/security_solution && yarn openapi:generate) +check_for_changed_files "yarn openapi:generate" true \ No newline at end of file diff --git a/.buildkite/scripts/steps/functional/common.sh b/.buildkite/scripts/steps/functional/common.sh index f9b77890030c9..e6d13190b32cb 100755 --- a/.buildkite/scripts/steps/functional/common.sh +++ b/.buildkite/scripts/steps/functional/common.sh @@ -21,3 +21,7 @@ if [[ -d "$cacheDir" ]]; then fi is_test_execution_step + +# logins into docker as a common step for functional tests +echo "$KIBANA_DOCKER_PASSWORD" | docker login -u "$KIBANA_DOCKER_USERNAME" --password-stdin docker.elastic.co +trap 'docker logout docker.elastic.co' EXIT diff --git a/.buildkite/scripts/steps/functional/security_serverless_osquery.sh b/.buildkite/scripts/steps/functional/security_serverless_osquery.sh index 60312fcaf681a..d631424552fa8 100755 --- a/.buildkite/scripts/steps/functional/security_serverless_osquery.sh +++ b/.buildkite/scripts/steps/functional/security_serverless_osquery.sh @@ -2,10 +2,13 @@ set -euo pipefail -source .buildkite/scripts/common/util.sh +source .buildkite/scripts/steps/functional/common.sh source .buildkite/scripts/steps/functional/common_cypress.sh -.buildkite/scripts/bootstrap.sh +# TODO: remove the line below to use build artifacts for tests. +# in addition to remove the line, we will have to expose the kibana install dir into the downloaded build location +# by exporting a var like: +# export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} node scripts/build_kibana_platform_plugins.js export JOB=kibana-osquery-cypress-serverless diff --git a/.buildkite/scripts/steps/functional/serverless_ftr.sh b/.buildkite/scripts/steps/functional/serverless_ftr.sh index ba75fe6034cae..335b4b97f1445 100755 --- a/.buildkite/scripts/steps/functional/serverless_ftr.sh +++ b/.buildkite/scripts/steps/functional/serverless_ftr.sh @@ -12,6 +12,10 @@ if [[ "$SERVERLESS_ENVIRONMENT" == "search" ]]; then "x-pack/test_serverless/api_integration/test_suites/search/config.feature_flags.ts" "x-pack/test_serverless/functional/test_suites/search/config.ts" ) +elif [[ "$SERVERLESS_ENVIRONMENT" == "search.examples" ]]; then + SERVERLESS_CONFIGS=( + "x-pack/test_serverless/functional/test_suites/search/config.examples.ts" + ) elif [[ "$SERVERLESS_ENVIRONMENT" == "observability" ]]; then SERVERLESS_CONFIGS=( "x-pack/test_serverless/api_integration/test_suites/observability/config.ts" @@ -19,15 +23,24 @@ elif [[ "$SERVERLESS_ENVIRONMENT" == "observability" ]]; then "x-pack/test_serverless/functional/test_suites/observability/config.ts" "x-pack/test_serverless/functional/test_suites/observability/cypress/config_headless.ts" ) +elif [[ "$SERVERLESS_ENVIRONMENT" == "observability.examples" ]]; then + SERVERLESS_CONFIGS=( + "x-pack/test_serverless/functional/test_suites/observability/config.examples.ts" + ) elif [[ "$SERVERLESS_ENVIRONMENT" == "security" ]]; then SERVERLESS_CONFIGS=( "x-pack/test_serverless/api_integration/test_suites/security/config.ts" "x-pack/test_serverless/api_integration/test_suites/security/config.feature_flags.ts" "x-pack/test_serverless/functional/test_suites/security/config.ts" ) +elif [[ "$SERVERLESS_ENVIRONMENT" == "security.examples" ]]; then + SERVERLESS_CONFIGS=( + "x-pack/test_serverless/functional/test_suites/security/config.examples.ts" + ) fi EXIT_CODE=0 +OFFENDING_CONFIG= for CONFIG in "${SERVERLESS_CONFIGS[@]}" do @@ -42,7 +55,17 @@ do if [ $LAST_CODE -ne 0 ]; then EXIT_CODE=10 + OFFENDING_CONFIG=$CONFIG fi done +echo "--- Serverless FTR Results for $JOB" +if [ $EXIT_CODE -eq 0 ]; then + echo "✅ Success!" +elif [ $EXIT_CODE -eq 10 ]; then + echo "❌ Failed in config: $OFFENDING_CONFIG, exit code set to 10 for soft-failure" +else + echo "❌ Failed." +fi + exit $EXIT_CODE diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.ts b/.buildkite/scripts/steps/storybooks/build_and_upload.ts index e9014da1cefae..2afc5f4037148 100644 --- a/.buildkite/scripts/steps/storybooks/build_and_upload.ts +++ b/.buildkite/scripts/steps/storybooks/build_and_upload.ts @@ -26,7 +26,7 @@ const STORYBOOKS = [ 'dashboard_enhanced', 'dashboard', 'data', - 'discover_log_explorer', + 'log_explorer', 'embeddable', 'expression_error', 'expression_image', diff --git a/.buildkite/scripts/steps/test/jest_integration.sh b/.buildkite/scripts/steps/test/jest_integration.sh index fd7b9a1d6ad54..6ebff3ae984b8 100755 --- a/.buildkite/scripts/steps/test/jest_integration.sh +++ b/.buildkite/scripts/steps/test/jest_integration.sh @@ -8,5 +8,9 @@ is_test_execution_step .buildkite/scripts/bootstrap.sh +echo '--- Docker login' +echo "$KIBANA_DOCKER_PASSWORD" | docker login -u "$KIBANA_DOCKER_USERNAME" --password-stdin docker.elastic.co +trap 'docker logout docker.elastic.co' EXIT + echo '--- Jest Integration Tests' .buildkite/scripts/steps/test/jest_parallel.sh jest.integration.config.js diff --git a/.eslintrc.js b/.eslintrc.js index ddd39ed00747a..5b5ef73ed3806 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -984,6 +984,7 @@ module.exports = { // front end and common typescript and javascript files only files: [ 'x-pack/plugins/ecs_data_quality_dashboard/common/**/*.{js,mjs,ts,tsx}', + 'x-pack/plugins/elastic_assistant/common/**/*.{js,mjs,ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{js,mjs,ts,tsx}', 'x-pack/packages/security-solution/**/*.{js,mjs,ts,tsx}', 'x-pack/plugins/security_solution/public/**/*.{js,mjs,ts,tsx}', @@ -1016,6 +1017,7 @@ module.exports = { // This should be a very small set as most linter rules are useful for tests as well. files: [ 'x-pack/plugins/ecs_data_quality_dashboard/**/*.{ts,tsx}', + 'x-pack/plugins/elastic_assistant/**/*.{ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{ts,tsx}', 'x-pack/packages/security-solution/**/*.{ts,tsx}', 'x-pack/plugins/security_solution/**/*.{ts,tsx}', @@ -1026,6 +1028,7 @@ module.exports = { ], excludedFiles: [ 'x-pack/plugins/ecs_data_quality_dashboard/**/*.{test,mock,test_helper}.{ts,tsx}', + 'x-pack/plugins/elastic_assistant/**/*.{test,mock,test_helper}.{ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{test,mock,test_helper}.{ts,tsx}', 'x-pack/packages/security-solution/**/*.{test,mock,test_helper}.{ts,tsx}', 'x-pack/plugins/security_solution/**/*.{test,mock,test_helper}.{ts,tsx}', @@ -1042,6 +1045,7 @@ module.exports = { // typescript only for front and back end files: [ 'x-pack/plugins/ecs_data_quality_dashboard/**/*.{ts,tsx}', + 'x-pack/plugins/elastic_assistant/**/*.{ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{ts,tsx}', 'x-pack/packages/security-solution/**/*.{ts,tsx}', 'x-pack/plugins/security_solution/**/*.{ts,tsx}', @@ -1077,6 +1081,7 @@ module.exports = { // typescript and javascript for front and back end files: [ 'x-pack/plugins/ecs_data_quality_dashboard/**/*.{js,mjs,ts,tsx}', + 'x-pack/plugins/elastic_assistant/**/*.{js,mjs,ts,tsx}', 'x-pack/packages/kbn-elastic-assistant/**/*.{js,mjs,ts,tsx}', 'x-pack/packages/security-solution/**/*.{js,mjs,ts,tsx}', 'x-pack/plugins/security_solution/**/*.{js,mjs,ts,tsx}', @@ -1175,6 +1180,7 @@ module.exports = { overrides: [ { files: [ + 'x-pack/packages/security-solution/features/**/*.{js,mjs,ts,tsx}', 'x-pack/packages/security-solution/navigation/**/*.{js,mjs,ts,tsx}', 'x-pack/plugins/security_solution/**/*.{js,mjs,ts,tsx}', 'x-pack/plugins/security_solution_ess/**/*.{js,mjs,ts,tsx}', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 911bfb5161dc0..cd4fe15e8827c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -329,7 +329,6 @@ packages/kbn-dev-utils @elastic/kibana-operations examples/developer_examples @elastic/appex-sharedux examples/discover_customization_examples @elastic/kibana-data-discovery x-pack/plugins/discover_enhanced @elastic/kibana-data-discovery -x-pack/plugins/discover_log_explorer @elastic/infra-monitoring-ui src/plugins/discover @elastic/kibana-data-discovery packages/kbn-discover-utils @elastic/kibana-data-discovery packages/kbn-doc-links @elastic/docs @@ -340,6 +339,7 @@ packages/kbn-ecs @elastic/kibana-core @elastic/security-threat-hunting-investiga x-pack/packages/security-solution/ecs_data_quality_dashboard @elastic/security-threat-hunting-investigations x-pack/plugins/ecs_data_quality_dashboard @elastic/security-threat-hunting-investigations x-pack/packages/kbn-elastic-assistant @elastic/security-solution +x-pack/plugins/elastic_assistant @elastic/security-solution test/plugin_functional/plugins/elasticsearch_client_plugin @elastic/kibana-core x-pack/test/plugin_api_integration/plugins/elasticsearch_client @elastic/kibana-core x-pack/plugins/embeddable_enhanced @elastic/kibana-presentation @@ -471,6 +471,7 @@ packages/kbn-lint-ts-projects-cli @elastic/kibana-operations x-pack/plugins/lists @elastic/security-detection-engine examples/locator_examples @elastic/kibana-app-services examples/locator_explorer @elastic/kibana-app-services +x-pack/plugins/log_explorer @elastic/infra-monitoring-ui packages/kbn-logging @elastic/kibana-core packages/kbn-logging-mocks @elastic/kibana-core x-pack/plugins/logs_shared @elastic/infra-monitoring-ui @@ -517,11 +518,13 @@ x-pack/plugins/monitoring @elastic/infra-monitoring-ui src/plugins/navigation @elastic/appex-sharedux src/plugins/newsfeed @elastic/kibana-core test/common/plugins/newsfeed @elastic/kibana-core +src/plugins/no_data_page @elastic/appex-sharedux x-pack/plugins/notifications @elastic/appex-sharedux packages/kbn-object-versioning @elastic/appex-sharedux x-pack/plugins/observability_ai_assistant @elastic/obs-ai-assistant x-pack/packages/observability/alert_details @elastic/actionable-observability x-pack/test/cases_api_integration/common/plugins/observability @elastic/response-ops +x-pack/plugins/observability_log_explorer @elastic/infra-monitoring-ui x-pack/plugins/observability_onboarding @elastic/apm-ui x-pack/plugins/observability @elastic/actionable-observability x-pack/plugins/observability_shared @elastic/observability-ui @@ -542,6 +545,7 @@ packages/kbn-plugin-helpers @elastic/kibana-operations examples/portable_dashboards_example @elastic/kibana-presentation examples/preboot_example @elastic/kibana-security @elastic/kibana-core src/plugins/presentation_util @elastic/kibana-presentation +x-pack/plugins/profiling_data_access @elastic/profiling-ui x-pack/plugins/profiling @elastic/profiling-ui x-pack/packages/kbn-random-sampling @elastic/kibana-visualizations packages/kbn-react-field @elastic/kibana-data-discovery @@ -598,6 +602,7 @@ x-pack/plugins/searchprofiler @elastic/platform-deployment-management x-pack/test/security_api_integration/packages/helpers @elastic/kibana-security x-pack/plugins/security @elastic/kibana-security x-pack/plugins/security_solution_ess @elastic/security-solution +x-pack/packages/security-solution/features @elastic/security-threat-hunting-explore x-pack/test/cases_api_integration/common/plugins/security_solution @elastic/response-ops x-pack/packages/security-solution/navigation @elastic/security-threat-hunting-explore x-pack/plugins/security_solution @elastic/security-solution @@ -746,6 +751,10 @@ test/plugin_functional/plugins/ui_settings_plugin @elastic/kibana-core packages/kbn-ui-shared-deps-npm @elastic/kibana-operations packages/kbn-ui-shared-deps-src @elastic/kibana-operations packages/kbn-ui-theme @elastic/kibana-operations +packages/kbn-unified-data-table @elastic/kibana-data-discovery +packages/kbn-unified-doc-viewer @elastic/kibana-data-discovery +examples/unified_doc_viewer @elastic/kibana-core +src/plugins/unified_doc_viewer @elastic/kibana-data-discovery packages/kbn-unified-field-list @elastic/kibana-data-discovery examples/unified_field_list_examples @elastic/kibana-data-discovery src/plugins/unified_histogram @elastic/kibana-data-discovery @@ -824,6 +833,19 @@ packages/kbn-yarn-lock-validator @elastic/kibana-operations /x-pack/test/stack_functional_integration/apps/ccs/ccs_discover.js @elastic/kibana-data-discovery /x-pack/test/stack_functional_integration/apps/management/_index_pattern_create.js @elastic/kibana-data-discovery /x-pack/test/upgrade/apps/discover @elastic/kibana-data-discovery +/x-pack/test_serverless/api_integration/test_suites/common/data_views @elastic/kibana-data-discovery +/x-pack/test_serverless/api_integration/test_suites/common/data_view_field_editor @elastic/kibana-data-discovery +/x-pack/test_serverless/api_integration/test_suites/common/kql_telemetry @elastic/kibana-data-discovery +/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests @elastic/kibana-data-discovery +/x-pack/test_serverless/api_integration/test_suites/common/search_oss @elastic/kibana-data-discovery +/x-pack/test_serverless/api_integration/test_suites/common/search_xpack @elastic/kibana-data-discovery +/x-pack/test_serverless/functional/test_suites/common/examples/data_view_field_editor_example @elastic/kibana-data-discovery +/x-pack/test_serverless/functional/test_suites/common/examples/discover_customization_examples @elastic/kibana-data-discovery +/x-pack/test_serverless/functional/test_suites/common/examples/field_formats @elastic/kibana-data-discovery +/x-pack/test_serverless/functional/test_suites/common/examples/partial_results @elastic/kibana-data-discovery +/x-pack/test_serverless/functional/test_suites/common/examples/search @elastic/kibana-data-discovery +/x-pack/test_serverless/functional/test_suites/common/examples/search_examples @elastic/kibana-data-discovery +/x-pack/test_serverless/functional/test_suites/common/examples/unified_field_list_examples @elastic/kibana-data-discovery # Visualizations /src/plugins/visualize/ @elastic/kibana-visualizations @@ -1035,6 +1057,7 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /.github/codeql @elastic/kibana-security /.github/workflows/codeql.yml @elastic/kibana-security /src/dev/eslint/security_eslint_rule_tests.ts @elastic/kibana-security +/src/core/server/integration_tests/config/check_dynamic_config.test.ts @elastic/kibana-security /src/plugins/telemetry/server/config/telemetry_labels.ts @elastic/kibana-security /test/interactive_setup_api_integration/ @elastic/kibana-security /test/interactive_setup_functional/ @elastic/kibana-security diff --git a/.github/workflows/create-deploy-tag.yml b/.github/workflows/create-deploy-tag.yml new file mode 100644 index 0000000000000..ec06f8c11b49d --- /dev/null +++ b/.github/workflows/create-deploy-tag.yml @@ -0,0 +1,187 @@ +--- +# - This workflow creates a tag with the format "deploy@" on the main branch. +# - It is triggered manually from the GitHub Actions UI. +# - It is only allowed to run on the main branch and ensures that the tag is created +# on the main branch only in a verification step. +# This is only to prevent accidental creation of the tag on other branches and cannot be used to prevent malicious creation of the tag. + +name: "Serverless: Promote to QA" + +on: + workflow_dispatch: + inputs: + commit: + description: "Commit to promote (default: latest commit on main)" + +concurrency: + group: ${{ github.workflow }} + +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"]', github.triggering_actor) + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Select commit to be tagged + run: | + commit="${{ github.event.inputs.commit || github.sha }}" + echo "COMMIT=${commit}" >> "${GITHUB_ENV}" + - name: Verify selected or newer commit isn't already tagged + run: | + git tag --contains ${COMMIT} | grep -P "^deploy@\d+$" && { + echo "A deploy-tag already exists on the selected or newer commit!" + exit 1 + } || true + - name: Verify branch + run: | + if [[ "${GITHUB_REF}" != "refs/heads/main" ]]; then + echo "This workflow can only be run on the main branch" + exit 1 + fi + - name: Prepare tag + run: | + tag_name="deploy@$(date +%s)" + echo "TAG_NAME=${tag_name}" >> "${GITHUB_ENV}" + - name: Create tag + run: | + git tag ${TAG_NAME} ${COMMIT} + git push origin "refs/tags/${TAG_NAME}" + - name: Post Slack success message + if: success() + uses: slackapi/slack-github-action@v1.24.0 + with: + payload: | + { + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "A new has been promoted to QA 🎉\n\nOnce promotion is complete, please begin any required manual testing.\n\n*Remember:* Promotion to Staging is currently a manual process and will proceed once the build is signed off in QA." + } + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "*Initiated by:*\n" + }, + { + "type": "mrkdwn", + "text": "*Workflow run:*\n" + }, + { + "type": "mrkdwn", + "text": "*Commit:*\n" + }, + { + "type": "mrkdwn", + "text": "*Git tag:*\n" + } + ] + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Expected Staging promotion date:" + }, + "accessory": { + "type": "datepicker", + "placeholder": { + "type": "plain_text", + "text": "Select a date", + "emoji": true + }, + "action_id": "datepicker-action" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Useful links:*\n\n • \n • " + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Day 1 to-do list*" + }, + "accessory": { + "type": "checkboxes", + "options": [ + { + "text": { + "type": "mrkdwn", + "text": "Verify successful promotion to QA" + }, + "value": "value-0" + }, + { + "text": { + "type": "mrkdwn", + "text": "Notify Security Solution team to beging manual testing" + }, + "value": "value-1" + } + ], + "action_id": "checkboxes-action" + } + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.DEPLOY_TAGGER_SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + - name: Post Slack failure message + if: failure() + uses: slackapi/slack-github-action@v1.24.0 + with: + payload: | + { + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Promotion of to QA failed ⛔️" + } + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "*Initiated by:*\n" + }, + { + "type": "mrkdwn", + "text": "*Workflow run:*\n" + }, + { + "type": "mrkdwn", + "text": "*Commit:*\n" + } + ] + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Useful links:*\n\n • " + } + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.DEPLOY_TAGGER_SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.i18nrc.json b/.i18nrc.json index 2463d023971ed..eb098a7011a15 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -122,9 +122,11 @@ "visTypeXy": "src/plugins/vis_types/xy", "visualizations": "src/plugins/visualizations", "visualizationUiComponents": "packages/kbn-visualization-ui-components", + "unifiedDocViewer": ["src/plugins/unified_doc_viewer", "packages/kbn-unified-doc-viewer"], "unifiedSearch": "src/plugins/unified_search", "unifiedFieldList": "packages/kbn-unified-field-list", - "unifiedHistogram": "src/plugins/unified_histogram" + "unifiedHistogram": "src/plugins/unified_histogram", + "unifiedDataTable": "packages/kbn-unified-data-table" }, "translations": [] } diff --git a/api_docs/actions.devdocs.json b/api_docs/actions.devdocs.json index 12eec5ba79786..ab2fd467cd958 100644 --- a/api_docs/actions.devdocs.json +++ b/api_docs/actions.devdocs.json @@ -3247,9 +3247,7 @@ "section": "def-common.ActionTypeExecutorResult", "text": "ActionTypeExecutorResult" }, - ">; enqueueExecution: (options: ", - "ExecuteOptions", - ") => Promise; bulkEnqueueExecution: (options: ", + ">; bulkEnqueueExecution: (options: ", "ExecuteOptions", "[]) => Promise; ephemeralEnqueuedExecution: (options: ", "ExecuteOptions", @@ -3261,14 +3259,10 @@ "section": "def-server.RunNowResult", "text": "RunNowResult" }, - ">; listTypes: ({ featureId, includeSystemActionTypes, }?: ListTypesOptions) => Promise<", - { - "pluginId": "actions", - "scope": "common", - "docId": "kibActionsPluginApi", - "section": "def-common.ActionType", - "text": "ActionType" - }, + ">; listTypes: ({ featureId, includeSystemActionTypes, }?: ", + "ListTypesParams", + ") => Promise<", + "ConnectorType", "[]>; isActionTypeEnabled: (actionTypeId: string, options?: { notifyUsage: boolean; }) => boolean; isPreconfigured: (connectorId: string) => boolean; isSystemAction: (connectorId: string) => boolean; getGlobalExecutionLogWithAuth: ({ dateStart, dateEnd, filter, page, perPage, sort, namespaces, }: ", { "pluginId": "actions", diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index da628063c0e39..899ca0915da84 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.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 | |-------------------|-----------|------------------------|-----------------| -| 267 | 0 | 261 | 28 | +| 267 | 0 | 261 | 30 | ## Client diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 0dde21f314ebd..866a72b268d5b 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-08-25 +date: 2023-09-04 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 8c20255fbad0d..9403658cadad8 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-08-25 +date: 2023-09-04 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 5006dc01838c2..b6e47ef82750d 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -108,13 +108,13 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/es_query/index.ts" - }, { "plugin": "ml", "path": "x-pack/plugins/ml/public/alerting/register_ml_alerts.ts" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/es_query/index.ts" } ], "children": [ @@ -900,7 +900,9 @@ "\nInstalls index template that uses installed component template\nPrior to installation, simulates the installation to check for possible\nconflicts. Simulate should return an empty mapping if a template\nconflicts with an already installed template." ], "signature": [ - "({ logger, esClient, indexPatterns, totalFieldsLimit, }: CreateConcreteWriteIndexOpts) => Promise" + "(opts: ", + "CreateConcreteWriteIndexOpts", + ") => Promise" ], "path": "x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.ts", "deprecated": false, @@ -911,7 +913,7 @@ "id": "def-server.createConcreteWriteIndex.$1", "type": "Object", "tags": [], - "label": "{\n logger,\n esClient,\n indexPatterns,\n totalFieldsLimit,\n}", + "label": "opts", "description": [], "signature": [ "CreateConcreteWriteIndexOpts" @@ -968,7 +970,7 @@ "\nCreates ILM policy if it doesn't already exist, updates it if it does" ], "signature": [ - "({ logger, esClient, name, policy, }: CreateOrUpdateIlmPolicyOpts) => Promise" + "({ logger, esClient, name, policy, dataStreamAdapter, }: CreateOrUpdateIlmPolicyOpts) => Promise" ], "path": "x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_ilm_policy.ts", "deprecated": false, @@ -979,7 +981,7 @@ "id": "def-server.createOrUpdateIlmPolicy.$1", "type": "Object", "tags": [], - "label": "{\n logger,\n esClient,\n name,\n policy,\n}", + "label": "{\n logger,\n esClient,\n name,\n policy,\n dataStreamAdapter,\n}", "description": [], "signature": [ "CreateOrUpdateIlmPolicyOpts" @@ -1062,6 +1064,48 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "alerting", + "id": "def-server.getDataStreamAdapter", + "type": "Function", + "tags": [], + "label": "getDataStreamAdapter", + "description": [], + "signature": [ + "(opts: ", + "GetDataStreamAdapterOpts", + ") => ", + { + "pluginId": "alerting", + "scope": "server", + "docId": "kibAlertingPluginApi", + "section": "def-server.DataStreamAdapter", + "text": "DataStreamAdapter" + } + ], + "path": "x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.getDataStreamAdapter.$1", + "type": "Object", + "tags": [], + "label": "opts", + "description": [], + "signature": [ + "GetDataStreamAdapterOpts" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "alerting", "id": "def-server.getEsErrorMessage", @@ -1105,7 +1149,7 @@ "label": "getIndexTemplate", "description": [], "signature": [ - "({ componentTemplateRefs, ilmPolicyName, indexPatterns, kibanaVersion, namespace, totalFieldsLimit, }: GetIndexTemplateOpts) => ", + "({ componentTemplateRefs, ilmPolicyName, indexPatterns, kibanaVersion, namespace, totalFieldsLimit, dataStreamAdapter, }: GetIndexTemplateOpts) => ", "IndicesPutIndexTemplateRequest" ], "path": "x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_index_template.ts", @@ -1117,7 +1161,7 @@ "id": "def-server.getIndexTemplate.$1", "type": "Object", "tags": [], - "label": "{\n componentTemplateRefs,\n ilmPolicyName,\n indexPatterns,\n kibanaVersion,\n namespace,\n totalFieldsLimit,\n}", + "label": "{\n componentTemplateRefs,\n ilmPolicyName,\n indexPatterns,\n kibanaVersion,\n namespace,\n totalFieldsLimit,\n dataStreamAdapter,\n}", "description": [], "signature": [ "GetIndexTemplateOpts" @@ -1517,6 +1561,118 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "alerting", + "id": "def-server.DataStreamAdapter", + "type": "Interface", + "tags": [], + "label": "DataStreamAdapter", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DataStreamAdapter.isUsingDataStreams", + "type": "Function", + "tags": [], + "label": "isUsingDataStreams", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "alerting", + "id": "def-server.DataStreamAdapter.getIndexTemplateFields", + "type": "Function", + "tags": [], + "label": "getIndexTemplateFields", + "description": [], + "signature": [ + "(alias: string, pattern: string) => ", + "IndexTemplateFields" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DataStreamAdapter.getIndexTemplateFields.$1", + "type": "string", + "tags": [], + "label": "alias", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "alerting", + "id": "def-server.DataStreamAdapter.getIndexTemplateFields.$2", + "type": "string", + "tags": [], + "label": "pattern", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "alerting", + "id": "def-server.DataStreamAdapter.createStream", + "type": "Function", + "tags": [], + "label": "createStream", + "description": [], + "signature": [ + "(opts: ", + "CreateConcreteWriteIndexOpts", + ") => Promise" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DataStreamAdapter.createStream.$1", + "type": "Object", + "tags": [], + "label": "opts", + "description": [], + "signature": [ + "CreateConcreteWriteIndexOpts" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, { "parentPluginId": "alerting", "id": "def-server.FindResult", @@ -1894,7 +2050,7 @@ "section": "def-common.RuleTypeState", "text": "RuleTypeState" }, - ", InstanceState extends { [x: string]: unknown; } = { [x: string]: unknown; }, InstanceContext extends { [x: string]: unknown; } = { [x: string]: unknown; }, ActionGroupIds extends string = never, RecoveryActionGroupId extends string = never, AlertData extends ", + ", InstanceState extends Record = Record, InstanceContext extends { [x: string]: unknown; } = { [x: string]: unknown; }, ActionGroupIds extends string = never, RecoveryActionGroupId extends string = never, AlertData extends ", { "pluginId": "alerting", "scope": "common", @@ -1996,6 +2152,29 @@ "path": "x-pack/plugins/alerting/server/plugin.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "alerting", + "id": "def-server.PluginSetupContract.getDataStreamAdapter", + "type": "Function", + "tags": [], + "label": "getDataStreamAdapter", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "alerting", + "scope": "server", + "docId": "kibAlertingPluginApi", + "section": "def-server.DataStreamAdapter", + "text": "DataStreamAdapter" + } + ], + "path": "x-pack/plugins/alerting/server/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "initialIsOpen": false @@ -2101,7 +2280,7 @@ "section": "def-common.RuleTypeState", "text": "RuleTypeState" }, - ", InstanceState extends { [x: string]: unknown; } = { [x: string]: unknown; }, InstanceContext extends { [x: string]: unknown; } = { [x: string]: unknown; }, ActionGroupIds extends string = string, RecoveryActionGroupId extends string = string, AlertData extends ", + ", InstanceState extends Record = Record, InstanceContext extends { [x: string]: unknown; } = { [x: string]: unknown; }, ActionGroupIds extends string = string, RecoveryActionGroupId extends string = string, AlertData extends ", { "pluginId": "alerting", "scope": "common", @@ -3105,14 +3284,6 @@ "plugin": "ruleRegistry", "path": "x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts" }, - { - "plugin": "observability", - "path": "x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts" - }, - { - "plugin": "observability", - "path": "x-pack/plugins/observability/server/lib/rules/threshold/threshold_executor.ts" - }, { "plugin": "ml", "path": "x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts" @@ -3129,6 +3300,22 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/legacy_rules_notification_alert_type.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/server/lib/rules/threshold/threshold_executor.ts" + }, { "plugin": "infra", "path": "x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts" @@ -3157,14 +3344,6 @@ "plugin": "monitoring", "path": "x-pack/plugins/monitoring/server/alerts/base_rule.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/legacy_rules_notification_alert_type.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts" - }, { "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/server/rule_types/index_threshold/rule_type.ts" @@ -4197,21 +4376,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "alerting", - "id": "def-server.AlertInstanceState", - "type": "Type", - "tags": [], - "label": "AlertInstanceState", - "description": [], - "signature": [ - "{ [x: string]: unknown; }" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "alerting", "id": "def-server.BulkEditOperation", @@ -4333,6 +4497,21 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "alerting", + "id": "def-server.LatestAlertInstanceStateSchema", + "type": "Type", + "tags": [], + "label": "LatestAlertInstanceStateSchema", + "description": [], + "signature": [ + "{ [x: string]: any; }" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "alerting", "id": "def-server.PartialRule", @@ -4554,7 +4733,7 @@ }, ">; getAlertState: (params: ", "GetAlertStateParams", - ") => Promise; getAlertSummary: (params: ", + ") => Promise | undefined; alertInstances?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined; alertRecoveredInstances?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined; previousStartedAt?: string | null | undefined; summaryActions?: Record> | undefined; } & {}>>; getAlertSummary: (params: ", "GetAlertSummaryParams", ") => Promise<", { @@ -5529,67 +5708,6 @@ ], "returnComment": [], "initialIsOpen": false - }, - { - "parentPluginId": "alerting", - "id": "def-common.wrappedStateRt", - "type": "Function", - "tags": [], - "label": "wrappedStateRt", - "description": [], - "signature": [ - "() => ", - "TypeC", - "<{ wrapped: ", - "Type", - "; trackedAlerts: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ alertId: ", - "StringC", - "; alertUuid: ", - "StringC", - "; started: ", - "StringC", - "; flappingHistory: ", - "ArrayC", - "<", - "BooleanC", - ">; flapping: ", - "BooleanC", - "; pendingRecoveredCount: ", - "NumberC", - "; }>>; trackedAlertsRecovered: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ alertId: ", - "StringC", - "; alertUuid: ", - "StringC", - "; started: ", - "StringC", - "; flappingHistory: ", - "ArrayC", - "<", - "BooleanC", - ">; flapping: ", - "BooleanC", - "; pendingRecoveredCount: ", - "NumberC", - "; }>>; }>" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/lifecycle_state.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [], - "initialIsOpen": false } ], "interfaces": [ @@ -9389,18 +9507,6 @@ } ], "enums": [ - { - "parentPluginId": "alerting", - "id": "def-common.ActionsCompletion", - "type": "Enum", - "tags": [], - "label": "ActionsCompletion", - "description": [], - "path": "x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "alerting", "id": "def-common.HealthStatus", @@ -9539,36 +9645,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "alerting", - "id": "def-common.AlertInstanceMeta", - "type": "Type", - "tags": [], - "label": "AlertInstanceMeta", - "description": [], - "signature": [ - "{ lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; uuid?: string | undefined; }" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "alerting", - "id": "def-common.AlertInstanceState", - "type": "Type", - "tags": [], - "label": "AlertInstanceState", - "description": [], - "signature": [ - "{ [x: string]: unknown; }" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "alerting", "id": "def-common.ALERTS_FEATURE_ID", @@ -9848,15 +9924,90 @@ }, { "parentPluginId": "alerting", - "id": "def-common.LastScheduledActions", + "id": "def-common.LatestAlertInstanceMetaSchema", "type": "Type", "tags": [], - "label": "LastScheduledActions", + "label": "LatestAlertInstanceMetaSchema", "description": [], "signature": [ - "{ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }" + "{ readonly uuid?: string | undefined; readonly lastScheduledActions?: Readonly<{ actions?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; readonly flappingHistory?: boolean[] | undefined; readonly flapping?: boolean | undefined; readonly maintenanceWindowIds?: string[] | undefined; readonly pendingRecoveredCount?: number | undefined; }" ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "alerting", + "id": "def-common.LatestAlertInstanceStateSchema", + "type": "Type", + "tags": [], + "label": "LatestAlertInstanceStateSchema", + "description": [], + "signature": [ + "{ [x: string]: any; }" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "alerting", + "id": "def-common.LatestLastScheduledActionsSchema", + "type": "Type", + "tags": [], + "label": "LatestLastScheduledActionsSchema", + "description": [], + "signature": [ + "{ readonly actions?: Record> | undefined; readonly subgroup?: string | undefined; readonly date: string; readonly group: string; }" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "alerting", + "id": "def-common.LatestRawAlertInstanceSchema", + "type": "Type", + "tags": [], + "label": "LatestRawAlertInstanceSchema", + "description": [], + "signature": [ + "{ readonly meta?: Readonly<{ uuid?: string | undefined; lastScheduledActions?: Readonly<{ actions?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; readonly state?: Record | undefined; }" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "alerting", + "id": "def-common.LatestTaskStateSchema", + "type": "Type", + "tags": [], + "label": "LatestTaskStateSchema", + "description": [], + "signature": [ + "{ readonly alertTypeState?: Record | undefined; readonly alertInstances?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined; readonly alertRecoveredInstances?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined; readonly previousStartedAt?: string | null | undefined; readonly summaryActions?: Record> | undefined; }" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "alerting", + "id": "def-common.LatestThrottledActionSchema", + "type": "Type", + "tags": [], + "label": "LatestThrottledActionSchema", + "description": [], + "signature": [ + "{ [x: string]: Readonly<{} & { date: string; }>; }" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -10160,21 +10311,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "alerting", - "id": "def-common.RawAlertInstance", - "type": "Type", - "tags": [], - "label": "RawAlertInstance", - "description": [], - "signature": [ - "{ state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; uuid?: string | undefined; } | undefined; }" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "alerting", "id": "def-common.READ_FLAPPING_SETTINGS_SUB_FEATURE_ID", @@ -10622,21 +10758,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "alerting", - "id": "def-common.RuleTaskState", - "type": "Type", - "tags": [], - "label": "RuleTaskState", - "description": [], - "signature": [ - "{ alertTypeState?: { [x: string]: unknown; } | undefined; alertInstances?: { [x: string]: { state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; uuid?: string | undefined; } | undefined; }; } | undefined; alertRecoveredInstances?: { [x: string]: { state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; uuid?: string | undefined; } | undefined; }; } | undefined; previousStartedAt?: Date | null | undefined; summaryActions?: { [x: string]: { date: Date; }; } | undefined; }" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "alerting", "id": "def-common.RuleTypeParams", @@ -10752,21 +10873,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "alerting", - "id": "def-common.ThrottledActions", - "type": "Type", - "tags": [], - "label": "ThrottledActions", - "description": [], - "signature": [ - "{ [x: string]: { date: Date; }; }" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "alerting", "id": "def-common.TrackedLifecycleAlertState", @@ -12796,22 +12902,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "alerting", - "id": "def-common.DateFromString", - "type": "Object", - "tags": [], - "label": "DateFromString", - "description": [], - "signature": [ - "Type", - "" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/date_from_string.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "alerting", "id": "def-common.DEFAULT_FLAPPING_SETTINGS", @@ -13190,66 +13280,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "alerting", - "id": "def-common.rawAlertInstance", - "type": "Object", - "tags": [], - "label": "rawAlertInstance", - "description": [], - "signature": [ - "PartialC", - "<{ state: ", - "RecordC", - "<", - "StringC", - ", ", - "UnknownC", - ">; meta: ", - "PartialC", - "<{ lastScheduledActions: ", - "IntersectionC", - "<[", - "PartialC", - "<{ subgroup: ", - "StringC", - "; }>, ", - "TypeC", - "<{ group: ", - "StringC", - "; date: ", - "Type", - "; }>, ", - "PartialC", - "<{ actions: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ date: ", - "Type", - "; }>>; }>]>; flappingHistory: ", - "ArrayC", - "<", - "BooleanC", - ">; flapping: ", - "BooleanC", - "; maintenanceWindowIds: ", - "ArrayC", - "<", - "StringC", - ">; pendingRecoveredCount: ", - "NumberC", - "; uuid: ", - "StringC", - "; }>; }>" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "alerting", "id": "def-common.RecoveredActionGroup", @@ -13356,166 +13386,6 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false - }, - { - "parentPluginId": "alerting", - "id": "def-common.ruleParamsSchema", - "type": "Object", - "tags": [], - "label": "ruleParamsSchema", - "description": [], - "signature": [ - "IntersectionC", - "<[", - "TypeC", - "<{ alertId: ", - "StringC", - "; }>, ", - "PartialC", - "<{ spaceId: ", - "StringC", - "; }>]>" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "alerting", - "id": "def-common.ruleStateSchema", - "type": "Object", - "tags": [], - "label": "ruleStateSchema", - "description": [], - "signature": [ - "PartialC", - "<{ alertTypeState: ", - "RecordC", - "<", - "StringC", - ", ", - "UnknownC", - ">; alertInstances: ", - "RecordC", - "<", - "StringC", - ", ", - "PartialC", - "<{ state: ", - "RecordC", - "<", - "StringC", - ", ", - "UnknownC", - ">; meta: ", - "PartialC", - "<{ lastScheduledActions: ", - "IntersectionC", - "<[", - "PartialC", - "<{ subgroup: ", - "StringC", - "; }>, ", - "TypeC", - "<{ group: ", - "StringC", - "; date: ", - "Type", - "; }>, ", - "PartialC", - "<{ actions: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ date: ", - "Type", - "; }>>; }>]>; flappingHistory: ", - "ArrayC", - "<", - "BooleanC", - ">; flapping: ", - "BooleanC", - "; maintenanceWindowIds: ", - "ArrayC", - "<", - "StringC", - ">; pendingRecoveredCount: ", - "NumberC", - "; uuid: ", - "StringC", - "; }>; }>>; alertRecoveredInstances: ", - "RecordC", - "<", - "StringC", - ", ", - "PartialC", - "<{ state: ", - "RecordC", - "<", - "StringC", - ", ", - "UnknownC", - ">; meta: ", - "PartialC", - "<{ lastScheduledActions: ", - "IntersectionC", - "<[", - "PartialC", - "<{ subgroup: ", - "StringC", - "; }>, ", - "TypeC", - "<{ group: ", - "StringC", - "; date: ", - "Type", - "; }>, ", - "PartialC", - "<{ actions: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ date: ", - "Type", - "; }>>; }>]>; flappingHistory: ", - "ArrayC", - "<", - "BooleanC", - ">; flapping: ", - "BooleanC", - "; maintenanceWindowIds: ", - "ArrayC", - "<", - "StringC", - ">; pendingRecoveredCount: ", - "NumberC", - "; uuid: ", - "StringC", - "; }>; }>>; previousStartedAt: ", - "UnionC", - "<[", - "NullC", - ", ", - "Type", - "]>; summaryActions: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ date: ", - "Type", - "; }>>; }>" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false } ] } diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 33d37da346549..cce0276424e68 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-08-25 +date: 2023-09-04 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 | |-------------------|-----------|------------------------|-----------------| -| 786 | 1 | 755 | 46 | +| 790 | 1 | 759 | 49 | ## Client diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index 2007901b50001..e1b038257f9bf 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -408,7 +408,7 @@ "label": "APIEndpoint", "description": [], "signature": [ - "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/samples\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/error/{errorId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/services/{serviceName}/metrics/nodes\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/charts\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/summary\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/functions_overview\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/active_instances\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search 2023-10-31\" | \"POST /api/apm/services/{serviceName}/annotation 2023-10-31\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/services/{serviceName}/alerts_count\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/service-group/counts\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"POST /internal/apm/traces/aggregated_critical_path\" | \"GET /internal/apm/traces/{traceId}/transactions/{transactionId}\" | \"GET /internal/apm/traces/{traceId}/spans/{spanId}\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/rule_types/transaction_error_rate/chart_preview\" | \"GET /internal/apm/rule_types/error_count/chart_preview\" | \"GET /internal/apm/rule_types/transaction_duration/chart_preview\" | \"GET /api/apm/settings/agent-configuration 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/view 2023-10-31\" | \"DELETE /api/apm/settings/agent-configuration 2023-10-31\" | \"PUT /api/apm/settings/agent-configuration 2023-10-31\" | \"POST /api/apm/settings/agent-configuration/search 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/environments 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/agent_name 2023-10-31\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps 2023-10-31\" | \"POST /api/apm/sourcemaps 2023-10-31\" | \"DELETE /api/apm/sourcemaps/{id} 2023-10-31\" | \"POST /api/apm/androidmaps 2023-10-31\" | \"POST /internal/apm/sourcemaps/migrate_fleet_artifacts\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema 2023-10-31\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys 2023-10-31\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/storage_chart\" | \"GET /internal/apm/storage_explorer/privileges\" | \"GET /internal/apm/storage_explorer_summary_stats\" | \"GET /internal/apm/storage_explorer/is_cross_cluster_search\" | \"GET /internal/apm/storage_explorer/get_services\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\" | \"GET /internal/apm/settings/labs\" | \"GET /internal/apm/get_agents_per_service\" | \"GET /internal/apm/get_latest_agent_versions\" | \"GET /internal/apm/services/{serviceName}/agent_instances\" | \"GET /internal/apm/services/{serviceName}/mobile/filters\" | \"GET /internal/apm/mobile-services/{serviceName}/most_used_charts\" | \"GET /internal/apm/mobile-services/{serviceName}/transactions/charts/sessions\" | \"GET /internal/apm/mobile-services/{serviceName}/transactions/charts/http_requests\" | \"GET /internal/apm/mobile-services/{serviceName}/stats\" | \"GET /internal/apm/mobile-services/{serviceName}/location/stats\" | \"GET /internal/apm/mobile-services/{serviceName}/terms\" | \"GET /internal/apm/mobile-services/{serviceName}/main_statistics\" | \"GET /internal/apm/mobile-services/{serviceName}/detailed_statistics\" | \"GET /internal/apm/diagnostics\" | \"POST /internal/apm/assistant/get_apm_timeseries\" | \"GET /internal/apm/assistant/get_service_summary\" | \"GET /internal/apm/assistant/get_error_document\" | \"POST /internal/apm/assistant/get_correlation_values\" | \"GET /internal/apm/assistant/get_downstream_dependencies\"" + "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/samples\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/error/{errorId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/services/{serviceName}/metrics/nodes\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/charts\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/summary\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/functions_overview\" | \"GET /internal/apm/services/{serviceName}/metrics/serverless/active_instances\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search 2023-10-31\" | \"POST /api/apm/services/{serviceName}/annotation 2023-10-31\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/services/{serviceName}/alerts_count\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/service-group/counts\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"POST /internal/apm/traces/aggregated_critical_path\" | \"GET /internal/apm/traces/{traceId}/transactions/{transactionId}\" | \"GET /internal/apm/traces/{traceId}/spans/{spanId}\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/rule_types/transaction_error_rate/chart_preview\" | \"GET /internal/apm/rule_types/error_count/chart_preview\" | \"GET /internal/apm/rule_types/transaction_duration/chart_preview\" | \"GET /api/apm/settings/agent-configuration 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/view 2023-10-31\" | \"DELETE /api/apm/settings/agent-configuration 2023-10-31\" | \"PUT /api/apm/settings/agent-configuration 2023-10-31\" | \"POST /api/apm/settings/agent-configuration/search 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/environments 2023-10-31\" | \"GET /api/apm/settings/agent-configuration/agent_name 2023-10-31\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps 2023-10-31\" | \"POST /api/apm/sourcemaps 2023-10-31\" | \"DELETE /api/apm/sourcemaps/{id} 2023-10-31\" | \"POST /api/apm/androidmaps 2023-10-31\" | \"POST /internal/apm/sourcemaps/migrate_fleet_artifacts\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema 2023-10-31\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys 2023-10-31\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/storage_chart\" | \"GET /internal/apm/storage_explorer/privileges\" | \"GET /internal/apm/storage_explorer_summary_stats\" | \"GET /internal/apm/storage_explorer/is_cross_cluster_search\" | \"GET /internal/apm/storage_explorer/get_services\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\" | \"GET /internal/apm/settings/labs\" | \"GET /internal/apm/get_agents_per_service\" | \"GET /internal/apm/get_latest_agent_versions\" | \"GET /internal/apm/services/{serviceName}/agent_instances\" | \"GET /internal/apm/services/{serviceName}/mobile/filters\" | \"GET /internal/apm/mobile-services/{serviceName}/most_used_charts\" | \"GET /internal/apm/mobile-services/{serviceName}/transactions/charts/sessions\" | \"GET /internal/apm/mobile-services/{serviceName}/transactions/charts/http_requests\" | \"GET /internal/apm/mobile-services/{serviceName}/stats\" | \"GET /internal/apm/mobile-services/{serviceName}/location/stats\" | \"GET /internal/apm/mobile-services/{serviceName}/terms\" | \"GET /internal/apm/mobile-services/{serviceName}/main_statistics\" | \"GET /internal/apm/mobile-services/{serviceName}/detailed_statistics\" | \"GET /internal/apm/diagnostics\" | \"POST /internal/apm/assistant/get_apm_timeseries\" | \"GET /internal/apm/assistant/get_service_summary\" | \"GET /internal/apm/assistant/get_error_document\" | \"POST /internal/apm/assistant/get_correlation_values\" | \"GET /internal/apm/assistant/get_downstream_dependencies\" | \"GET /internal/apm/assistant/get_services_list\"" ], "path": "x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts", "deprecated": false, @@ -455,7 +455,73 @@ "label": "APMServerRouteRepository", "description": [], "signature": [ - "{ \"GET /internal/apm/assistant/get_downstream_dependencies\": { endpoint: \"GET /internal/apm/assistant/get_downstream_dependencies\"; params?: ", + "{ \"GET /internal/apm/assistant/get_services_list\": { endpoint: \"GET /internal/apm/assistant/get_services_list\"; params?: ", + "TypeC", + "<{ query: ", + "IntersectionC", + "<[", + "TypeC", + "<{ start: ", + "StringC", + "; end: ", + "StringC", + "; }>, ", + "PartialC", + "<{ 'service.environment': ", + "UnionC", + "<[", + "LiteralC", + "<\"ENVIRONMENT_NOT_DEFINED\">, ", + "LiteralC", + "<\"ENVIRONMENT_ALL\">, ", + "BrandC", + "<", + "StringC", + ", ", + { + "pluginId": "@kbn/io-ts-utils", + "scope": "common", + "docId": "kibKbnIoTsUtilsPluginApi", + "section": "def-common.NonEmptyStringBrand", + "text": "NonEmptyStringBrand" + }, + ">]>; healthStatus: ", + "ArrayC", + "<", + "UnionC", + "<[", + "LiteralC", + "<", + "ServiceHealthStatus", + ".unknown>, ", + "LiteralC", + "<", + "ServiceHealthStatus", + ".healthy>, ", + "LiteralC", + "<", + "ServiceHealthStatus", + ".warning>, ", + "LiteralC", + "<", + "ServiceHealthStatus", + ".critical>]>>; }>]>; }> | undefined; handler: ({}: ", + "APMRouteHandlerResources", + " & { params: { query: { start: string; end: string; } & { 'service.environment'?: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", + "Branded", + " | undefined; healthStatus?: ", + "ServiceHealthStatus", + "[] | undefined; }; }; }) => Promise<{ content: ApmServicesListContent; }>; } & ", + "APMRouteCreateOptions", + "; \"GET /internal/apm/assistant/get_downstream_dependencies\": { endpoint: \"GET /internal/apm/assistant/get_downstream_dependencies\"; params?: ", "TypeC", "<{ query: ", "IntersectionC", @@ -807,7 +873,7 @@ "IngestGetPipelineResponse", " | undefined; }; diagnosticsPrivileges: { index: Record; cluster: Record; hasAllClusterPrivileges: boolean; hasAllIndexPrivileges: boolean; hasAllPrivileges: boolean; }; apmIndices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; }>; apmIndexTemplates: { name: string; isNonStandard: boolean; exists: boolean; }[]; fleetPackageInfo: { isInstalled: boolean; version?: string | undefined; }; kibanaVersion: string; elasticsearchVersion: string; apmEvents: ", + ">; cluster: Record; hasAllClusterPrivileges: boolean; hasAllIndexPrivileges: boolean; hasAllPrivileges: boolean; }; apmIndices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; sourcemap: string; }>; apmIndexTemplates: { name: string; isNonStandard: boolean; exists: boolean; }[]; fleetPackageInfo: { isInstalled: boolean; version?: string | undefined; }; kibanaVersion: string; elasticsearchVersion: string; apmEvents: ", "ApmEvent", "[]; invalidIndices?: ", "IndiciesItem", @@ -3329,7 +3395,7 @@ "PartialC", "; }> | undefined; handler: ({}: ", "APMRouteHandlerResources", - " & { params: { body: { readonly error?: string | undefined; readonly metric?: string | undefined; readonly transaction?: string | undefined; readonly span?: string | undefined; readonly onboarding?: string | undefined; }; }; }) => Promise<", + " & { params: { body: { readonly error?: string | undefined; readonly metric?: string | undefined; readonly transaction?: string | undefined; readonly span?: string | undefined; readonly onboarding?: string | undefined; readonly sourcemap?: string | undefined; }; }; }) => Promise<", { "pluginId": "@kbn/core-saved-objects-common", "scope": "common", @@ -3341,7 +3407,7 @@ "APMRouteCreateOptions", "; \"GET /internal/apm/settings/apm-indices\": { endpoint: \"GET /internal/apm/settings/apm-indices\"; params?: undefined; handler: ({}: ", "APMRouteHandlerResources", - ") => Promise>; } & ", + ") => Promise>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/settings/apm-index-settings\": { endpoint: \"GET /internal/apm/settings/apm-index-settings\"; params?: undefined; handler: ({}: ", "APMRouteHandlerResources", @@ -3593,9 +3659,9 @@ "ArrayC", "<", "StringC", - ">; kqlFilter: ", - "StringC", - "; }>]>; }> | undefined; handler: ({}: ", + ">; searchConfiguration: ", + "Type", + "<{ query: { query: string | { [x: string]: any; }; language: string; }; }, string, unknown>; }>]>; }> | undefined; handler: ({}: ", "APMRouteHandlerResources", " & { params: { query: { aggregationType?: ", "AggregationType", @@ -3609,7 +3675,7 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; } & { start: number; end: number; } & { interval: string; } & { groupBy?: string[] | undefined; kqlFilter?: string | undefined; }; }; }) => Promise<{ latencyChartPreview: ", + ">; } & { start: number; end: number; } & { interval: string; } & { groupBy?: string[] | undefined; searchConfiguration?: { query: { query: string | { [x: string]: any; }; language: string; }; } | undefined; }; }; }) => Promise<{ latencyChartPreview: ", "PreviewChartResponse", "; }>; } & ", "APMRouteCreateOptions", @@ -3677,9 +3743,9 @@ "ArrayC", "<", "StringC", - ">; kqlFilter: ", - "StringC", - "; }>]>; }> | undefined; handler: ({}: ", + ">; searchConfiguration: ", + "Type", + "<{ query: { query: string | { [x: string]: any; }; language: string; }; }, string, unknown>; }>]>; }> | undefined; handler: ({}: ", "APMRouteHandlerResources", " & { params: { query: { aggregationType?: ", "AggregationType", @@ -3693,7 +3759,7 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; } & { start: number; end: number; } & { interval: string; } & { groupBy?: string[] | undefined; kqlFilter?: string | undefined; }; }; }) => Promise<{ errorCountChartPreview: ", + ">; } & { start: number; end: number; } & { interval: string; } & { groupBy?: string[] | undefined; searchConfiguration?: { query: { query: string | { [x: string]: any; }; language: string; }; } | undefined; }; }; }) => Promise<{ errorCountChartPreview: ", "PreviewChartResponse", "; }>; } & ", "APMRouteCreateOptions", @@ -3761,9 +3827,9 @@ "ArrayC", "<", "StringC", - ">; kqlFilter: ", - "StringC", - "; }>]>; }> | undefined; handler: ({}: ", + ">; searchConfiguration: ", + "Type", + "<{ query: { query: string | { [x: string]: any; }; language: string; }; }, string, unknown>; }>]>; }> | undefined; handler: ({}: ", "APMRouteHandlerResources", " & { params: { query: { aggregationType?: ", "AggregationType", @@ -3777,7 +3843,7 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; } & { start: number; end: number; } & { interval: string; } & { groupBy?: string[] | undefined; kqlFilter?: string | undefined; }; }; }) => Promise<{ errorRateChartPreview: ", + ">; } & { start: number; end: number; } & { interval: string; } & { groupBy?: string[] | undefined; searchConfiguration?: { query: { query: string | { [x: string]: any; }; language: string; }; } | undefined; }; }; }) => Promise<{ errorRateChartPreview: ", "PreviewChartResponse", "; }>; } & ", "APMRouteCreateOptions", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 073e5cf9b25dd..837369f938c06 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) for ques | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 29 | 0 | 29 | 118 | +| 29 | 0 | 29 | 119 | ## Client diff --git a/api_docs/apm_data_access.devdocs.json b/api_docs/apm_data_access.devdocs.json index aaab84fef1ef1..57fe58d681f92 100644 --- a/api_docs/apm_data_access.devdocs.json +++ b/api_docs/apm_data_access.devdocs.json @@ -22,7 +22,7 @@ "label": "APMDataAccessConfig", "description": [], "signature": [ - "{ readonly indices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; }>; }" + "{ readonly indices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; sourcemap: string; }>; }" ], "path": "x-pack/plugins/apm_data_access/server/index.ts", "deprecated": false, @@ -37,7 +37,7 @@ "label": "APMIndices", "description": [], "signature": [ - "{ readonly error: string; readonly metric: string; readonly transaction: string; readonly span: string; readonly onboarding: string; }" + "{ readonly error: string; readonly metric: string; readonly transaction: string; readonly span: string; readonly onboarding: string; readonly sourcemap: string; }" ], "path": "x-pack/plugins/apm_data_access/server/index.ts", "deprecated": false, @@ -65,7 +65,7 @@ "label": "apmIndicesFromConfigFile", "description": [], "signature": [ - "{ readonly error: string; readonly metric: string; readonly transaction: string; readonly span: string; readonly onboarding: string; }" + "{ readonly error: string; readonly metric: string; readonly transaction: string; readonly span: string; readonly onboarding: string; readonly sourcemap: string; }" ], "path": "x-pack/plugins/apm_data_access/server/types.ts", "deprecated": false, @@ -87,7 +87,7 @@ "section": "def-common.SavedObjectsClientContract", "text": "SavedObjectsClientContract" }, - ") => Promise>" + ") => Promise>" ], "path": "x-pack/plugins/apm_data_access/server/types.ts", "deprecated": false, diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index bf1ab4ebe9ad8..13727c4c1f12b 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-08-25 +date: 2023-09-04 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 32263f2f65e7c..dc48993d0222d 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-08-25 +date: 2023-09-04 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 26dacafa07677..873de52ad2f0c 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-08-25 +date: 2023-09-04 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 c47199bb5be57..f2d5f4479d27a 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-08-25 +date: 2023-09-04 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 08fe18d05cd52..dd1fe659f2303 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.devdocs.json b/api_docs/cases.devdocs.json index 15f422cdf22ba..5d00886d09ee8 100644 --- a/api_docs/cases.devdocs.json +++ b/api_docs/cases.devdocs.json @@ -1091,7 +1091,14 @@ "\nReturn the UI capabilities for each type of operation. These strings must match the values defined in the UI\nhere: x-pack/plugins/cases/public/client/helpers/capabilities.ts" ], "signature": [ - "() => { all: readonly [\"create_cases\", \"read_cases\", \"update_cases\", \"push_cases\", \"cases_connectors\"]; read: readonly [\"read_cases\", \"cases_connectors\"]; delete: readonly [\"delete_cases\"]; }" + "() => ", + { + "pluginId": "cases", + "scope": "common", + "docId": "kibCasesPluginApi", + "section": "def-common.CasesUiCapabilities", + "text": "CasesUiCapabilities" + } ], "path": "x-pack/plugins/cases/common/utils/capabilities.ts", "deprecated": false, @@ -1108,7 +1115,14 @@ "label": "getApiTags", "description": [], "signature": [ - "(owner: \"cases\" | \"observability\" | \"securitySolution\") => { all: readonly [\"casesSuggestUserProfiles\", \"bulkGetUserProfiles\", \"casesGetConnectorsConfigure\", string, string]; read: readonly [\"casesSuggestUserProfiles\", \"bulkGetUserProfiles\", \"casesGetConnectorsConfigure\", string]; delete: readonly [string]; }" + "(owner: \"cases\" | \"observability\" | \"securitySolution\") => ", + { + "pluginId": "cases", + "scope": "common", + "docId": "kibCasesPluginApi", + "section": "def-common.CasesApiTags", + "text": "CasesApiTags" + } ], "path": "x-pack/plugins/cases/common/utils/api_tags.ts", "deprecated": false, @@ -1236,6 +1250,62 @@ } ], "interfaces": [ + { + "parentPluginId": "cases", + "id": "def-common.CasesApiTags", + "type": "Interface", + "tags": [], + "label": "CasesApiTags", + "description": [], + "path": "x-pack/plugins/cases/common/utils/api_tags.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cases", + "id": "def-common.CasesApiTags.all", + "type": "Object", + "tags": [], + "label": "all", + "description": [], + "signature": [ + "readonly string[]" + ], + "path": "x-pack/plugins/cases/common/utils/api_tags.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cases", + "id": "def-common.CasesApiTags.read", + "type": "Object", + "tags": [], + "label": "read", + "description": [], + "signature": [ + "readonly string[]" + ], + "path": "x-pack/plugins/cases/common/utils/api_tags.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cases", + "id": "def-common.CasesApiTags.delete", + "type": "Object", + "tags": [], + "label": "delete", + "description": [], + "signature": [ + "readonly string[]" + ], + "path": "x-pack/plugins/cases/common/utils/api_tags.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "cases", "id": "def-common.CasesPermissions", @@ -1327,6 +1397,62 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "cases", + "id": "def-common.CasesUiCapabilities", + "type": "Interface", + "tags": [], + "label": "CasesUiCapabilities", + "description": [], + "path": "x-pack/plugins/cases/common/utils/capabilities.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cases", + "id": "def-common.CasesUiCapabilities.all", + "type": "Object", + "tags": [], + "label": "all", + "description": [], + "signature": [ + "readonly string[]" + ], + "path": "x-pack/plugins/cases/common/utils/capabilities.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cases", + "id": "def-common.CasesUiCapabilities.read", + "type": "Object", + "tags": [], + "label": "read", + "description": [], + "signature": [ + "readonly string[]" + ], + "path": "x-pack/plugins/cases/common/utils/capabilities.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cases", + "id": "def-common.CasesUiCapabilities.delete", + "type": "Object", + "tags": [], + "label": "delete", + "description": [], + "signature": [ + "readonly string[]" + ], + "path": "x-pack/plugins/cases/common/utils/capabilities.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "cases", "id": "def-common.Ecs", @@ -2031,6 +2157,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "cases", + "id": "def-common.CASES_CONNECTORS_CAPABILITY", + "type": "string", + "tags": [], + "label": "CASES_CONNECTORS_CAPABILITY", + "description": [], + "signature": [ + "\"cases_connectors\"" + ], + "path": "x-pack/plugins/cases/common/constants/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "cases", "id": "def-common.CASES_URL", @@ -2651,6 +2792,23 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "cases", + "id": "def-common.GET_CONNECTORS_CONFIGURE_API_TAG", + "type": "string", + "tags": [], + "label": "GET_CONNECTORS_CONFIGURE_API_TAG", + "description": [ + "\nThis tag is registered for the connectors (configure) get API" + ], + "signature": [ + "\"casesGetConnectorsConfigure\"" + ], + "path": "x-pack/plugins/cases/common/constants/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "cases", "id": "def-common.GetRelatedCasesByAlertResponse", diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index b92cc561c11fb..ead0c0c8d39bb 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.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 | |-------------------|-----------|------------------------|-----------------| -| 94 | 0 | 75 | 27 | +| 104 | 0 | 84 | 27 | ## Client diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index e2a39284f4ad7..9f2bb5580d01e 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-08-25 +date: 2023-09-04 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 701aa0aa7e6ea..b1edc370293f3 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index db98c2429dd22..64929c3feb971 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2023-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_chat_provider.mdx b/api_docs/cloud_chat_provider.mdx index a6e18728e4ed6..bc16410b14fa2 100644 --- a/api_docs/cloud_chat_provider.mdx +++ b/api_docs/cloud_chat_provider.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChatProvider title: "cloudChatProvider" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChatProvider plugin -date: 2023-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChatProvider'] --- import cloudChatProviderObj from './cloud_chat_provider.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index 5b8c930945103..e172da2aede66 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-08-25 +date: 2023-09-04 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 5b69cf66dc472..8164d8ba931d5 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-08-25 +date: 2023-09-04 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 4aaf1a463c157..d7e222a6ee385 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-08-25 +date: 2023-09-04 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 33408a91c0b55..a16a659373d90 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-08-25 +date: 2023-09-04 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 a8d7a69e03ec6..a21182e4f1fa2 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-08-25 +date: 2023-09-04 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 d6d6faf4e9159..148a26daba742 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-08-25 +date: 2023-09-04 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 51a0150e7b38e..4a1da09f9f920 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-08-25 +date: 2023-09-04 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 c8ea60ea91432..23b057247d2f4 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-08-25 +date: 2023-09-04 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 1d1815ffa76dd..9f32e7708d7c5 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-08-25 +date: 2023-09-04 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 4008a160485a1..bad94974edecd 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-08-25 +date: 2023-09-04 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 96d7a1cb5a1d9..31a0b4ae7ada9 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -7620,6 +7620,77 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "data", + "id": "def-public.DataPublicPluginStartActions.createFiltersFromMultiValueClickAction", + "type": "Function", + "tags": [], + "label": "createFiltersFromMultiValueClickAction", + "description": [], + "signature": [ + "({ data, negate, }: { data: { cells: { column: number; row: number; }[]; table: Pick<", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.Datatable", + "text": "Datatable" + }, + ", \"meta\" | \"rows\" | \"columns\">; relation?: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.BooleanRelation", + "text": "BooleanRelation" + }, + " | undefined; }[]; timeFieldName?: string | undefined; negate?: boolean | undefined; }) => Promise<", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Filter", + "text": "Filter" + }, + "[] | undefined>" + ], + "path": "src/plugins/data/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "data", + "id": "def-public.DataPublicPluginStartActions.createFiltersFromMultiValueClickAction.$1", + "type": "Object", + "tags": [], + "label": "__0", + "description": [], + "signature": [ + "{ data: { cells: { column: number; row: number; }[]; table: Pick<", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.Datatable", + "text": "Datatable" + }, + ", \"meta\" | \"rows\" | \"columns\">; relation?: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.BooleanRelation", + "text": "BooleanRelation" + }, + " | undefined; }[]; timeFieldName?: string | undefined; negate?: boolean | undefined; }" + ], + "path": "src/plugins/data/public/actions/filters/create_filters_from_multi_value_click.ts", + "deprecated": false, + "trackAdoption": false + } + ] } ], "initialIsOpen": false @@ -8807,10 +8878,6 @@ "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" }, - { - "plugin": "@kbn/core-saved-objects-browser-mocks", - "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" - }, { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" @@ -8823,22 +8890,6 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/logs.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/flights.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, { "plugin": "osquery", "path": "x-pack/plugins/osquery/server/routes/pack/read_pack_route.ts" @@ -8927,6 +8978,26 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-browser-mocks", + "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/logs.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/flights.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" + }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/rules_client/lib/siem_legacy_actions/retrieve_migrated_legacy_actions.mock.ts" @@ -12844,10 +12915,6 @@ "plugin": "dashboard", "path": "src/plugins/dashboard/public/services/data/data_service.ts" }, - { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/threshold/expression.tsx" - }, { "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_data_row/document_stats.tsx" @@ -12860,6 +12927,10 @@ "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_data_expanded_row/choropleth_map.tsx" }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/threshold/expression.tsx" + }, { "plugin": "expressionPartitionVis", "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts" @@ -13308,6 +13379,10 @@ "plugin": "@kbn/visualization-ui-components", "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" + }, { "plugin": "observability", "path": "x-pack/plugins/observability/public/components/threshold/hooks/use_metrics_explorer_data.ts" @@ -13368,10 +13443,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" - }, { "plugin": "timelines", "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" @@ -13556,6 +13627,18 @@ "plugin": "dataViews", "path": "src/plugins/data_views/common/data_views/data_view.ts" }, + { + "plugin": "logsShared", + "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + }, { "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" @@ -13596,6 +13679,10 @@ "plugin": "@kbn/unified-field-list", "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" }, + { + "plugin": "@kbn/unified-field-list", + "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" + }, { "plugin": "@kbn/event-annotation-components", "path": "packages/kbn-event-annotation-components/components/group_editor_controls/group_editor_controls.tsx" @@ -13608,25 +13695,93 @@ "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" }, - { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" }, { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" }, { "plugin": "ml", @@ -13645,8 +13800,8 @@ "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" }, { - "plugin": "logsShared", - "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" }, { "plugin": "visTypeTimeseries", @@ -13720,86 +13875,6 @@ "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx" }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" @@ -13884,29 +13959,25 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + "path": "x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts" }, { "plugin": "transform", @@ -21073,6 +21144,10 @@ "plugin": "@kbn/visualization-ui-components", "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" + }, { "plugin": "observability", "path": "x-pack/plugins/observability/public/components/threshold/hooks/use_metrics_explorer_data.ts" @@ -21133,10 +21208,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" - }, { "plugin": "timelines", "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" @@ -21321,6 +21392,18 @@ "plugin": "dataViews", "path": "src/plugins/data_views/common/data_views/data_view.ts" }, + { + "plugin": "logsShared", + "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + }, { "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" @@ -21361,6 +21444,10 @@ "plugin": "@kbn/unified-field-list", "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" }, + { + "plugin": "@kbn/unified-field-list", + "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" + }, { "plugin": "@kbn/event-annotation-components", "path": "packages/kbn-event-annotation-components/components/group_editor_controls/group_editor_controls.tsx" @@ -21373,25 +21460,93 @@ "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" }, - { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" }, { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" }, { "plugin": "ml", @@ -21410,8 +21565,8 @@ "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" }, { - "plugin": "logsShared", - "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" }, { "plugin": "visTypeTimeseries", @@ -21485,86 +21640,6 @@ "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx" }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" @@ -21649,29 +21724,25 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + "path": "x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts" }, { "plugin": "transform", @@ -27866,10 +27937,6 @@ "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" }, - { - "plugin": "@kbn/core-saved-objects-browser-mocks", - "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" - }, { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" @@ -27882,22 +27949,6 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/logs.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/flights.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, { "plugin": "osquery", "path": "x-pack/plugins/osquery/server/routes/pack/read_pack_route.ts" @@ -27986,6 +28037,26 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-browser-mocks", + "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/logs.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/flights.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" + }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/rules_client/lib/siem_legacy_actions/retrieve_migrated_legacy_actions.mock.ts" diff --git a/api_docs/data.mdx b/api_docs/data.mdx index c02169f95e7f1..cd8663c63a4dd 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-08-25 +date: 2023-09-04 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 | |-------------------|-----------|------------------------|-----------------| -| 3308 | 33 | 2581 | 26 | +| 3311 | 33 | 2584 | 26 | ## Client diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index a2c68c7b8d9b7..d26d267c9a539 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-08-25 +date: 2023-09-04 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 | |-------------------|-----------|------------------------|-----------------| -| 3308 | 33 | 2581 | 26 | +| 3311 | 33 | 2584 | 26 | ## Client diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index 3b5cd7151721e..ceb9136800672 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -32457,6 +32457,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "data", + "id": "def-common.ESQL_SEARCH_STRATEGY", + "type": "string", + "tags": [], + "label": "ESQL_SEARCH_STRATEGY", + "description": [], + "signature": [ + "\"esql\"" + ], + "path": "src/plugins/data/common/search/strategies/esql_search/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "data", "id": "def-common.EsQuerySearchAfter", diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 38885b13974ae..2d057a13b84aa 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-08-25 +date: 2023-09-04 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 | |-------------------|-----------|------------------------|-----------------| -| 3308 | 33 | 2581 | 26 | +| 3311 | 33 | 2584 | 26 | ## Client diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 4de32fe60d84a..9b47727c9e7f8 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-08-25 +date: 2023-09-04 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 89dd821b47ea8..3b8f58af0e36b 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-08-25 +date: 2023-09-04 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 ef85f7588de19..b2bbfbc401b91 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-08-25 +date: 2023-09-04 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 f57fd958ff546..347f1f24fed09 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -71,6 +71,10 @@ "plugin": "@kbn/visualization-ui-components", "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" + }, { "plugin": "observability", "path": "x-pack/plugins/observability/public/components/threshold/hooks/use_metrics_explorer_data.ts" @@ -131,10 +135,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" - }, { "plugin": "timelines", "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" @@ -303,6 +303,10 @@ "plugin": "@kbn/es-query", "path": "packages/kbn-es-query/src/kuery/functions/utils/get_full_field_name_node.test.ts" }, + { + "plugin": "data", + "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" + }, { "plugin": "data", "path": "src/plugins/data/common/search/search_source/inspect/inspector_stats.ts" @@ -313,15 +317,15 @@ }, { "plugin": "data", - "path": "src/plugins/data/common/search/aggs/param_types/field.ts" + "path": "src/plugins/data/public/search/errors/painless_error.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" + "path": "src/plugins/data/common/search/aggs/param_types/field.ts" }, { - "plugin": "data", - "path": "src/plugins/data/public/search/errors/painless_error.tsx" + "plugin": "logsShared", + "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" }, { "plugin": "savedObjectsManagement", @@ -363,6 +367,10 @@ "plugin": "@kbn/unified-field-list", "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" }, + { + "plugin": "@kbn/unified-field-list", + "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" + }, { "plugin": "@kbn/event-annotation-components", "path": "packages/kbn-event-annotation-components/components/group_editor_controls/group_editor_controls.tsx" @@ -375,10 +383,6 @@ "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" }, - { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" @@ -387,6 +391,86 @@ "plugin": "triggersActionsUi", "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts" @@ -404,8 +488,8 @@ "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" }, { - "plugin": "logsShared", - "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" }, { "plugin": "visTypeTimeseries", @@ -479,86 +563,6 @@ "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx" }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" @@ -643,29 +647,25 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + "path": "x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts" }, { "plugin": "transform", @@ -8035,6 +8035,10 @@ "plugin": "@kbn/visualization-ui-components", "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" + }, { "plugin": "observability", "path": "x-pack/plugins/observability/public/components/threshold/hooks/use_metrics_explorer_data.ts" @@ -8095,10 +8099,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" - }, { "plugin": "timelines", "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" @@ -8267,6 +8267,10 @@ "plugin": "@kbn/es-query", "path": "packages/kbn-es-query/src/kuery/functions/utils/get_full_field_name_node.test.ts" }, + { + "plugin": "data", + "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" + }, { "plugin": "data", "path": "src/plugins/data/common/search/search_source/inspect/inspector_stats.ts" @@ -8277,15 +8281,15 @@ }, { "plugin": "data", - "path": "src/plugins/data/common/search/aggs/param_types/field.ts" + "path": "src/plugins/data/public/search/errors/painless_error.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" + "path": "src/plugins/data/common/search/aggs/param_types/field.ts" }, { - "plugin": "data", - "path": "src/plugins/data/public/search/errors/painless_error.tsx" + "plugin": "logsShared", + "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" }, { "plugin": "savedObjectsManagement", @@ -8327,6 +8331,10 @@ "plugin": "@kbn/unified-field-list", "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" }, + { + "plugin": "@kbn/unified-field-list", + "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" + }, { "plugin": "@kbn/event-annotation-components", "path": "packages/kbn-event-annotation-components/components/group_editor_controls/group_editor_controls.tsx" @@ -8339,10 +8347,6 @@ "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" }, - { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" @@ -8351,6 +8355,86 @@ "plugin": "triggersActionsUi", "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts" @@ -8368,8 +8452,8 @@ "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" }, { - "plugin": "logsShared", - "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" }, { "plugin": "visTypeTimeseries", @@ -8443,86 +8527,6 @@ "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx" }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" @@ -8607,29 +8611,25 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + "path": "x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts" }, { "plugin": "transform", @@ -15109,6 +15109,10 @@ "plugin": "@kbn/visualization-ui-components", "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" + }, { "plugin": "observability", "path": "x-pack/plugins/observability/public/components/threshold/hooks/use_metrics_explorer_data.ts" @@ -15169,10 +15173,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts" - }, { "plugin": "timelines", "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" @@ -15341,6 +15341,10 @@ "plugin": "@kbn/es-query", "path": "packages/kbn-es-query/src/kuery/functions/utils/get_full_field_name_node.test.ts" }, + { + "plugin": "data", + "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" + }, { "plugin": "data", "path": "src/plugins/data/common/search/search_source/inspect/inspector_stats.ts" @@ -15351,15 +15355,15 @@ }, { "plugin": "data", - "path": "src/plugins/data/common/search/aggs/param_types/field.ts" + "path": "src/plugins/data/public/search/errors/painless_error.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" + "path": "src/plugins/data/common/search/aggs/param_types/field.ts" }, { - "plugin": "data", - "path": "src/plugins/data/public/search/errors/painless_error.tsx" + "plugin": "logsShared", + "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" }, { "plugin": "savedObjectsManagement", @@ -15401,6 +15405,10 @@ "plugin": "@kbn/unified-field-list", "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" }, + { + "plugin": "@kbn/unified-field-list", + "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" + }, { "plugin": "@kbn/event-annotation-components", "path": "packages/kbn-event-annotation-components/components/group_editor_controls/group_editor_controls.tsx" @@ -15413,10 +15421,6 @@ "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" }, - { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" @@ -15425,6 +15429,86 @@ "plugin": "triggersActionsUi", "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts" @@ -15442,8 +15526,8 @@ "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" }, { - "plugin": "logsShared", - "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" }, { "plugin": "visTypeTimeseries", @@ -15517,86 +15601,6 @@ "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx" }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" @@ -15681,29 +15685,25 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/flyout/preview/components/rule_preview.tsx" }, { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" }, { "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + "path": "x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts" }, { "plugin": "transform", @@ -24441,10 +24441,6 @@ "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" }, - { - "plugin": "@kbn/core-saved-objects-browser-mocks", - "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" - }, { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" @@ -24457,22 +24453,6 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/logs.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/flights.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, { "plugin": "osquery", "path": "x-pack/plugins/osquery/server/routes/pack/read_pack_route.ts" @@ -24561,6 +24541,26 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-browser-mocks", + "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/logs.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/flights.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" + }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/rules_client/lib/siem_legacy_actions/retrieve_migrated_legacy_actions.mock.ts" diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index c66942232e6d2..21ccdfb785eba 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 13037fde33fb8..d0731896513df 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 39f1fced54178..216ac502d9391 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -16,37 +16,36 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Referencing plugin(s) | Remove By | | ---------------|-----------|-----------| -| | stackAlerts, ml | - | -| | ruleRegistry, observability, ml, infra, monitoring, securitySolution, stackAlerts, synthetics, transform, uptime | - | +| | ml, stackAlerts | - | +| | ruleRegistry, ml, securitySolution, observability, infra, monitoring, stackAlerts, synthetics, transform, uptime | - | +| | @kbn/es-query, @kbn/visualization-ui-components, securitySolution, observability, timelines, lists, threatIntelligence, savedSearch, dataViews, logsShared, savedObjectsManagement, unifiedSearch, controls, @kbn/unified-field-list, @kbn/event-annotation-components, lens, triggersActionsUi, dataVisualizer, ml, visTypeTimeseries, apm, exploratoryView, fleet, stackAlerts, infra, canvas, enterpriseSearch, graph, transform, upgradeAssistant, uptime, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, data | - | +| | @kbn/es-query, @kbn/visualization-ui-components, securitySolution, observability, timelines, lists, threatIntelligence, savedSearch, dataViews, logsShared, savedObjectsManagement, unifiedSearch, controls, @kbn/unified-field-list, @kbn/event-annotation-components, lens, triggersActionsUi, dataVisualizer, ml, visTypeTimeseries, apm, exploratoryView, fleet, stackAlerts, infra, canvas, enterpriseSearch, graph, transform, upgradeAssistant, uptime, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, data | - | +| | @kbn/es-query, @kbn/visualization-ui-components, securitySolution, observability, timelines, lists, threatIntelligence, savedSearch, data, logsShared, savedObjectsManagement, unifiedSearch, controls, @kbn/unified-field-list, @kbn/event-annotation-components, lens, triggersActionsUi, dataVisualizer, ml, visTypeTimeseries, apm, exploratoryView, fleet, stackAlerts, infra, canvas, enterpriseSearch, graph, transform, upgradeAssistant, uptime, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega | - | +| | home, data, esUiShared, savedObjectsManagement, ml, exploratoryView, fleet, observability, apm, indexLifecycleManagement, observabilityOnboarding, synthetics, upgradeAssistant, uptime, ux, kibanaOverview | - | +| | share, uiActions, guidedOnboarding, home, management, spaces, security, savedObjects, indexManagement, serverless, visualizations, controls, dashboard, savedObjectsTagging, expressionXY, lens, expressionMetricVis, expressionGauge, alerting, triggersActionsUi, cases, licenseManagement, advancedSettings, maps, dataVisualizer, aiops, ml, exploratoryView, fleet, observability, infra, profiling, apm, expressionImage, expressionMetric, expressionError, expressionRevealImage, expressionRepeatImage, expressionShape, crossClusterReplication, enterpriseSearch, globalSearchBar, graph, grokdebugger, indexLifecycleManagement, ingestPipelines, logstash, monitoring, observabilityOnboarding, osquery, devTools, painlessLab, remoteClusters, rollup, searchprofiler, newsfeed, securitySolution, snapshotRestore, synthetics, transform, upgradeAssistant, uptime, ux, watcher, cloudDataMigration, console, filesManagement, kibanaOverview, visDefaultEditor, expressionHeatmap, expressionLegacyMetricVis, expressionPartitionVis, expressionTagcloud, visTypeTable, visTypeTimelion, visTypeTimeseries, visTypeVega, visTypeVislib | - | +| | encryptedSavedObjects, actions, data, ml, securitySolution, logstash, cloudChat | - | +| | actions, ml, savedObjectsTagging, enterpriseSearch | - | +| | @kbn/core-saved-objects-browser-internal, @kbn/core, savedObjects, presentationUtil, visualizations, dataVisualizer, ml, aiops, dashboardEnhanced, graph, lens, securitySolution, eventAnnotation, @kbn/core-saved-objects-browser-mocks | - | +| | @kbn/core, ml, savedObjects, embeddable, visualizations, canvas, graph, @kbn/core-saved-objects-common, @kbn/core-saved-objects-server, actions, alerting, securitySolution, savedSearch, enterpriseSearch, taskManager, @kbn/core-saved-objects-server-internal, @kbn/core-saved-objects-api-server | - | | | stackAlerts, alerting, securitySolution, inputControlVis | - | | | stackAlerts, infra, graph, inputControlVis, securitySolution, savedObjects | - | -| | dashboard, stackAlerts, dataVisualizer, expressionPartitionVis | - | -| | @kbn/es-query, @kbn/visualization-ui-components, observability, securitySolution, timelines, lists, threatIntelligence, savedSearch, dataViews, savedObjectsManagement, unifiedSearch, controls, @kbn/unified-field-list, @kbn/event-annotation-components, lens, triggersActionsUi, ml, logsShared, visTypeTimeseries, apm, exploratoryView, fleet, stackAlerts, dataVisualizer, infra, canvas, enterpriseSearch, graph, transform, upgradeAssistant, uptime, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, data | - | +| | dashboard, dataVisualizer, stackAlerts, expressionPartitionVis | - | | | stackAlerts, alerting, securitySolution, inputControlVis | - | -| | @kbn/es-query, @kbn/visualization-ui-components, observability, securitySolution, timelines, lists, threatIntelligence, savedSearch, dataViews, savedObjectsManagement, unifiedSearch, controls, @kbn/unified-field-list, @kbn/event-annotation-components, lens, triggersActionsUi, ml, logsShared, visTypeTimeseries, apm, exploratoryView, fleet, stackAlerts, dataVisualizer, infra, canvas, enterpriseSearch, graph, transform, upgradeAssistant, uptime, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, data | - | -| | @kbn/es-query, @kbn/visualization-ui-components, observability, securitySolution, timelines, lists, threatIntelligence, savedSearch, data, savedObjectsManagement, unifiedSearch, controls, @kbn/unified-field-list, @kbn/event-annotation-components, lens, triggersActionsUi, ml, logsShared, visTypeTimeseries, apm, exploratoryView, fleet, stackAlerts, dataVisualizer, infra, canvas, enterpriseSearch, graph, transform, upgradeAssistant, uptime, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega | - | -| | home, data, esUiShared, savedObjectsManagement, exploratoryView, fleet, observability, ml, apm, indexLifecycleManagement, observabilityOnboarding, synthetics, upgradeAssistant, uptime, ux, kibanaOverview | - | -| | share, uiActions, guidedOnboarding, home, management, spaces, savedObjects, controls, serverless, visualizations, dashboard, savedObjectsTagging, expressionXY, lens, expressionMetricVis, expressionGauge, security, alerting, triggersActionsUi, cases, aiops, exploratoryView, fleet, observability, licenseManagement, advancedSettings, maps, dataVisualizer, ml, infra, profiling, apm, expressionImage, expressionMetric, expressionError, expressionRevealImage, expressionRepeatImage, expressionShape, indexManagement, crossClusterReplication, enterpriseSearch, globalSearchBar, graph, grokdebugger, indexLifecycleManagement, ingestPipelines, logstash, monitoring, observabilityOnboarding, osquery, devTools, painlessLab, remoteClusters, rollup, searchprofiler, newsfeed, securitySolution, serverlessSearch, snapshotRestore, synthetics, transform, upgradeAssistant, uptime, ux, watcher, cloudDataMigration, console, filesManagement, kibanaOverview, visDefaultEditor, expressionHeatmap, expressionLegacyMetricVis, expressionPartitionVis, expressionTagcloud, visTypeTable, visTypeTimelion, visTypeTimeseries, visTypeVega, visTypeVislib | - | -| | encryptedSavedObjects, actions, data, ml, logstash, securitySolution, cloudChat | - | -| | actions, ml, savedObjectsTagging, enterpriseSearch | - | -| | @kbn/core-saved-objects-browser-internal, @kbn/core, savedObjects, presentationUtil, visualizations, aiops, ml, dataVisualizer, dashboardEnhanced, graph, lens, securitySolution, eventAnnotation, @kbn/core-saved-objects-browser-mocks | - | -| | @kbn/core, ml, savedObjects, embeddable, visualizations, canvas, graph, @kbn/core-saved-objects-common, @kbn/core-saved-objects-server, actions, alerting, savedSearch, enterpriseSearch, securitySolution, taskManager, @kbn/core-saved-objects-server-internal, @kbn/core-saved-objects-api-server | - | -| | inspector, data, savedObjects, dataViewEditor, unifiedSearch, embeddable, controls, visualizations, dashboard, licensing, savedObjectsTagging, eventAnnotation, dataViewFieldEditor, lens, security, triggersActionsUi, cases, observabilityShared, exploratoryView, fleet, observability, telemetry, advancedSettings, maps, banners, reporting, timelines, cloudSecurityPosture, runtimeFields, indexManagement, dashboardEnhanced, imageEmbeddable, graph, monitoring, securitySolution, synthetics, transform, uptime, cloudLinks, console, dataViewManagement, filesManagement, uiActions, visTypeVislib | - | -| | observability, @kbn/securitysolution-data-table, securitySolution | - | -| | monitoring | - | | | alerting, discover, securitySolution | - | -| | @kbn/core-saved-objects-api-server-internal, @kbn/core-saved-objects-import-export-server-internal, @kbn/core-saved-objects-server-internal, @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, home, @kbn/core-saved-objects-browser-mocks, fleet, graph, lists, osquery, securitySolution, alerting | - | -| | @kbn/core-saved-objects-api-server-internal, @kbn/core-saved-objects-import-export-server-internal, @kbn/core-saved-objects-server-internal, @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, home, @kbn/core-saved-objects-browser-mocks, fleet, graph, lists, osquery, securitySolution, alerting | - | +| | @kbn/core-saved-objects-api-server-internal, @kbn/core-saved-objects-import-export-server-internal, @kbn/core-saved-objects-server-internal, @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, home, fleet, osquery, securitySolution, @kbn/core-saved-objects-browser-mocks, graph, lists, alerting | - | +| | @kbn/core-saved-objects-api-server-internal, @kbn/core-saved-objects-import-export-server-internal, @kbn/core-saved-objects-server-internal, @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, home, fleet, osquery, securitySolution, @kbn/core-saved-objects-browser-mocks, graph, lists, alerting | - | | | alerting, discover, securitySolution | - | | | securitySolution | - | +| | inspector, data, licensing, security, savedObjects, runtimeFields, indexManagement, dataViewEditor, unifiedSearch, embeddable, visualizations, controls, dashboard, savedObjectsTagging, dataViewFieldEditor, eventAnnotation, lens, triggersActionsUi, cases, observabilityShared, telemetry, advancedSettings, maps, exploratoryView, fleet, observability, banners, reporting, timelines, cloudSecurityPosture, dashboardEnhanced, imageEmbeddable, graph, monitoring, securitySolution, synthetics, uptime, cloudLinks, console, dataViewManagement, filesManagement, uiActions, visTypeVislib | - | +| | observability, @kbn/securitysolution-data-table, securitySolution | - | | | @kbn/securitysolution-data-table, securitySolution | - | | | securitySolution | - | -| | @kbn/securitysolution-data-table, securitySolution | - | -| | @kbn/securitysolution-data-table, securitySolution | - | +| | securitySolution, @kbn/securitysolution-data-table | - | +| | securitySolution, @kbn/securitysolution-data-table | - | | | securitySolution | - | | | securitySolution | - | -| | @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, @kbn/core, savedObjectsTaggingOss, savedObjectsTagging, lists, securitySolution, upgradeAssistant, savedObjectsManagement, @kbn/core-saved-objects-api-server, @kbn/core-saved-objects-import-export-server-internal, home, canvas, savedObjects, @kbn/core-saved-objects-browser-mocks, @kbn/core-ui-settings-server-internal | - | -| | @kbn/core-saved-objects-migration-server-internal, actions, dataViews, data, alerting, lens, cases, savedObjectsTagging, visualizations, savedSearch, canvas, graph, lists, maps, securitySolution, dashboard, @kbn/core-test-helpers-so-type-serializer | - | +| | @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, @kbn/core, savedObjectsTaggingOss, savedObjectsTagging, securitySolution, lists, upgradeAssistant, savedObjectsManagement, @kbn/core-saved-objects-api-server, @kbn/core-saved-objects-import-export-server-internal, home, canvas, savedObjects, @kbn/core-saved-objects-browser-mocks, @kbn/core-ui-settings-server-internal | - | +| | @kbn/core-saved-objects-migration-server-internal, actions, dataViews, data, alerting, lens, lists, savedObjectsTagging, securitySolution, cases, visualizations, savedSearch, canvas, graph, maps, dashboard, @kbn/core-test-helpers-so-type-serializer | - | | | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | | | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | | | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | @@ -59,7 +58,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | securitySolution | - | | | securitySolution | - | | | securitySolution | - | -| | exploratoryView, fleet, dataVisualizer, cloudSecurityPosture, discoverEnhanced, osquery, synthetics | - | +| | monitoring | - | +| | dataVisualizer, exploratoryView, fleet, cloudSecurityPosture, discoverEnhanced, osquery, synthetics | - | | | @kbn/core-plugins-browser-internal, @kbn/core-root-browser-internal, home, savedObjects, unifiedSearch, presentationUtil, visualizations, fileUpload, dashboardEnhanced, transform, discover, dataVisualizer | - | | | @kbn/core, @kbn/core-lifecycle-browser, @kbn/core-saved-objects-browser-internal, visualizations, exploratoryView, transform, @kbn/core-saved-objects-browser-mocks | - | | | actions, alerting | - | @@ -70,12 +70,11 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | @kbn/core-saved-objects-api-server-internal | - | | | @kbn/core-saved-objects-api-server-internal | - | | | @kbn/core-saved-objects-api-server-internal, canvas, @kbn/core-saved-objects-browser-internal | - | -| | @kbn/core-saved-objects-server-internal, @kbn/core-plugins-server-internal, savedObjectsTagging, @kbn/core-saved-objects-server-mocks | - | -| | @kbn/core, kibanaUtils, expressions, data, savedObjectsTaggingOss, embeddable, controls, visualizations, savedObjectsTagging, uiActionsEnhanced, lens, maps, canvas, dashboardEnhanced, globalSearchProviders, @kbn/core-saved-objects-api-browser, savedObjects, savedObjectsManagement, eventAnnotation, graph, dashboard | - | +| | @kbn/core, kibanaUtils, expressions, data, savedObjectsTaggingOss, embeddable, visualizations, controls, savedObjectsTagging, uiActionsEnhanced, lens, maps, canvas, dashboardEnhanced, globalSearchProviders, @kbn/core-saved-objects-api-browser, savedObjects, savedObjectsManagement, eventAnnotation, graph, dashboard | - | | | @kbn/core-saved-objects-browser, @kbn/core-saved-objects-browser-internal, @kbn/core, home, savedObjects, visualizations, lens, visTypeTimeseries, @kbn/core-saved-objects-browser-mocks | - | | | @kbn/core-saved-objects-browser-internal, savedObjects, @kbn/core-saved-objects-browser-mocks | - | | | home, @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-browser-internal | - | -| | @kbn/core-saved-objects-browser-internal, savedObjects, @kbn/core-saved-objects-browser-mocks, visualizations | - | +| | @kbn/core-saved-objects-browser-internal, savedObjects, visualizations, @kbn/core-saved-objects-browser-mocks | - | | | @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-browser-internal | - | | | savedObjects, presentationUtil, @kbn/core-saved-objects-browser-mocks, dashboardEnhanced, @kbn/core-saved-objects-browser-internal | - | | | savedObjects, @kbn/core-saved-objects-browser-mocks, dashboardEnhanced, @kbn/core-saved-objects-browser-internal | - | @@ -141,8 +140,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | @kbn/core-lifecycle-browser-mocks, @kbn/core, @kbn/core-plugins-browser-internal | - | | | @kbn/core | - | | | @kbn/core-plugins-server-internal | - | -| | security, aiops, licenseManagement, ml, profiling, apm, crossClusterReplication, logstash, painlessLab, searchprofiler, watcher | 8.8.0 | -| | spaces, security, actions, alerting, ml, remoteClusters, graph, indexLifecycleManagement, mapsEms, osquery, painlessLab, rollup, searchprofiler, securitySolution, snapshotRestore, transform, upgradeAssistant | 8.8.0 | +| | security, licenseManagement, aiops, ml, profiling, apm, crossClusterReplication, logstash, painlessLab, searchprofiler, watcher | 8.8.0 | +| | spaces, security, actions, alerting, ml, osquery, securitySolution, remoteClusters, graph, indexLifecycleManagement, mapsEms, painlessLab, rollup, searchprofiler, snapshotRestore, transform, upgradeAssistant | 8.8.0 | | | apm, fleet, security, securitySolution | 8.8.0 | | | apm, fleet, security, securitySolution | 8.8.0 | | | spaces, security, alerting | 8.8.0 | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index e788d157af8a2..2c9c6e2863f3f 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -107,7 +107,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [plugin_context.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts#:~:text=legacy), [plugin_context.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts#:~:text=legacy) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/plugin.ts#:~:text=AsyncPlugin), [plugin.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/plugin.ts#:~:text=AsyncPlugin) | 8.8.0 | | | [plugin_manifest_parser.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/discovery/plugin_manifest_parser.ts#:~:text=extraPublicDirs), [plugin_manifest_parser.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/discovery/plugin_manifest_parser.ts#:~:text=extraPublicDirs), [plugin_manifest_parser.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/discovery/plugin_manifest_parser.ts#:~:text=extraPublicDirs), [plugin_manifest_parser.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/discovery/plugin_manifest_parser.ts#:~:text=extraPublicDirs), [plugin_manifest_parser.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/discovery/plugin_manifest_parser.ts#:~:text=extraPublicDirs), [plugin_manifest_parser.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/discovery/plugin_manifest_parser.ts#:~:text=extraPublicDirs) | - | -| | [plugin_context.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts#:~:text=getAllIndices), [plugin_context.ts](https://github.com/elastic/kibana/tree/main/packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts#:~:text=getAllIndices) | - | @@ -266,15 +265,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [import_dashboards.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts#:~:text=migrationVersion) | - | | | [import_dashboards.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts#:~:text=migrationVersion), [import_dashboards.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts#:~:text=migrationVersion), [import_dashboards.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts#:~:text=migrationVersion), [import_dashboards.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts#:~:text=migrationVersion) | - | | | [collect_references_deep.test.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/collect_references_deep.test.ts#:~:text=SavedObjectAttributes), [collect_references_deep.test.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/collect_references_deep.test.ts#:~:text=SavedObjectAttributes), [collect_references_deep.test.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/collect_references_deep.test.ts#:~:text=SavedObjectAttributes), [collect_references_deep.test.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/collect_references_deep.test.ts#:~:text=SavedObjectAttributes) | - | -| | [saved_objects_service.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts#:~:text=getAllIndices) | - | - - - -## @kbn/core-saved-objects-server-mocks - -| Deprecated API | Reference location(s) | Remove By | -| ---------------|-----------|-----------| -| | [saved_objects_service.mock.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts#:~:text=getAllIndices), [saved_objects_service.mock.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts#:~:text=getAllIndices) | - | @@ -572,9 +562,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [inspector_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts#:~:text=title), [response_writer.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/tabify/response_writer.ts#:~:text=title), [field.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=title), [get_display_value.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts#:~:text=title), [painless_error.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/errors/painless_error.tsx#:~:text=title), [agg_config.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/agg_config.test.ts#:~:text=title), [_terms_other_bucket_helper.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [rare_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/rare_terms.test.ts#:~:text=title)+ 3 more | - | -| | [inspector_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts#:~:text=title), [response_writer.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/tabify/response_writer.ts#:~:text=title), [field.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=title), [get_display_value.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts#:~:text=title), [painless_error.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/errors/painless_error.tsx#:~:text=title), [agg_config.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/agg_config.test.ts#:~:text=title), [_terms_other_bucket_helper.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [rare_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/rare_terms.test.ts#:~:text=title)+ 3 more | - | -| | [inspector_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts#:~:text=title), [response_writer.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/tabify/response_writer.ts#:~:text=title), [field.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=title), [get_display_value.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts#:~:text=title), [painless_error.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/errors/painless_error.tsx#:~:text=title), [agg_config.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/agg_config.test.ts#:~:text=title), [_terms_other_bucket_helper.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [rare_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/rare_terms.test.ts#:~:text=title)+ 3 more | - | +| | [get_display_value.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts#:~:text=title), [inspector_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts#:~:text=title), [response_writer.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/tabify/response_writer.ts#:~:text=title), [painless_error.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/errors/painless_error.tsx#:~:text=title), [field.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=title), [agg_config.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/agg_config.test.ts#:~:text=title), [_terms_other_bucket_helper.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [rare_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/rare_terms.test.ts#:~:text=title)+ 3 more | - | +| | [get_display_value.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts#:~:text=title), [inspector_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts#:~:text=title), [response_writer.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/tabify/response_writer.ts#:~:text=title), [painless_error.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/errors/painless_error.tsx#:~:text=title), [field.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=title), [agg_config.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/agg_config.test.ts#:~:text=title), [_terms_other_bucket_helper.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [rare_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/rare_terms.test.ts#:~:text=title)+ 3 more | - | +| | [get_display_value.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts#:~:text=title), [inspector_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts#:~:text=title), [response_writer.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/tabify/response_writer.ts#:~:text=title), [painless_error.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/errors/painless_error.tsx#:~:text=title), [field.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=title), [agg_config.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/agg_config.test.ts#:~:text=title), [_terms_other_bucket_helper.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [multi_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts#:~:text=title), [rare_terms.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/rare_terms.test.ts#:~:text=title)+ 3 more | - | | | [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), [shard_failure_open_modal_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/shard_failure_modal/shard_failure_open_modal_button.tsx#:~:text=toMountPoint), [shard_failure_open_modal_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/shard_failure_modal/shard_failure_open_modal_button.tsx#:~:text=toMountPoint), [handle_warnings.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/fetch/handle_warnings.tsx#:~:text=toMountPoint), [handle_warnings.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/fetch/handle_warnings.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), [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)+ 8 more | - | | | [get_columns.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/lib/get_columns.tsx#:~:text=RedirectAppLinks), [get_columns.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/lib/get_columns.tsx#:~:text=RedirectAppLinks), [get_columns.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/lib/get_columns.tsx#:~:text=RedirectAppLinks), [connected_search_session_indicator.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/session_indicator/connected_search_session_indicator/connected_search_session_indicator.tsx#:~:text=RedirectAppLinks), [connected_search_session_indicator.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/session_indicator/connected_search_session_indicator/connected_search_session_indicator.tsx#:~:text=RedirectAppLinks), [connected_search_session_indicator.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/session_indicator/connected_search_session_indicator/connected_search_session_indicator.tsx#:~:text=RedirectAppLinks) | - | | | [session_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/server/search/session/session_service.ts#:~:text=authc) | - | @@ -1189,9 +1179,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | ---------------|-----------|-----------| | | [register_ml_alerts.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/alerting/register_ml_alerts.ts#:~:text=registerNavigation) | - | | | [register_jobs_monitoring_rule_type.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts#:~:text=alertFactory), [register_jobs_monitoring_rule_type.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts#:~:text=alertFactory), [register_anomaly_detection_alert_type.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts#:~:text=alertFactory), [register_anomaly_detection_alert_type.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts#:~:text=alertFactory) | - | -| | [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts#:~:text=title), [rollup.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts#:~:text=title), [alerting_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/lib/alerts/alerting_service.ts#:~:text=title), [data_recognizer.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts#:~:text=title), [configuration_step_details.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx#:~:text=title), [data_loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title)+ 38 more | - | -| | [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts#:~:text=title), [rollup.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts#:~:text=title), [alerting_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/lib/alerts/alerting_service.ts#:~:text=title), [data_recognizer.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts#:~:text=title), [configuration_step_details.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx#:~:text=title), [data_loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title)+ 38 more | - | -| | [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts#:~:text=title), [rollup.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts#:~:text=title), [alerting_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/lib/alerts/alerting_service.ts#:~:text=title), [data_recognizer.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts#:~:text=title), [configuration_step_details.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx#:~:text=title), [data_loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title)+ 14 more | - | +| | [configuration_step_details.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx#:~:text=title), [data_loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [configuration_step_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx#:~:text=title), [configuration_step_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx#:~:text=title), [configuration_step_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx#:~:text=title), [page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx#:~:text=title)+ 38 more | - | +| | [configuration_step_details.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx#:~:text=title), [data_loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [configuration_step_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx#:~:text=title), [configuration_step_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx#:~:text=title), [configuration_step_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx#:~:text=title), [page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx#:~:text=title)+ 38 more | - | +| | [configuration_step_details.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx#:~:text=title), [data_loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [configuration_step_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx#:~:text=title), [configuration_step_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx#:~:text=title), [configuration_step_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx#:~:text=title), [page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx#:~:text=title)+ 14 more | - | | | [jobs_list_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx#:~:text=RedirectAppLinks), [jobs_list_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx#:~:text=RedirectAppLinks), [jobs_list_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx#:~:text=RedirectAppLinks) | - | | | [anomaly_charts_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx#:~:text=KibanaThemeProvider), [anomaly_charts_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx#:~:text=KibanaThemeProvider), [anomaly_charts_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx#:~:text=KibanaThemeProvider), [anomaly_swimlane_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx#:~:text=KibanaThemeProvider), [anomaly_swimlane_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx#:~:text=KibanaThemeProvider), [anomaly_swimlane_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable.tsx#:~:text=KibanaThemeProvider), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/app.tsx#:~:text=KibanaThemeProvider), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/app.tsx#:~:text=KibanaThemeProvider), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/app.tsx#:~:text=KibanaThemeProvider), [jobs_list_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx#:~:text=KibanaThemeProvider)+ 2 more | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/plugin.ts#:~:text=license%24) | 8.8.0 | @@ -1398,7 +1388,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [request_handler_context.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/server/request_handler_context.ts#:~:text=authz) | - | | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/types.ts#:~:text=SavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/types.ts#:~:text=SavedObject), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/utils.ts#:~:text=SavedObject), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/utils.ts#:~:text=SavedObject), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/utils.test.ts#:~:text=SavedObject), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/utils.test.ts#:~:text=SavedObject), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/utils.test.ts#:~:text=SavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts#:~:text=SavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts#:~:text=SavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts#:~:text=SavedObject)+ 3 more | - | | | [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/utils.ts#:~:text=SavedObjectReference), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/utils.ts#:~:text=SavedObjectReference), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/utils.ts#:~:text=SavedObjectReference), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/utils.ts#:~:text=SavedObjectReference)+ 11 more | - | -| | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/server/plugin.ts#:~:text=getAllIndices) | - | | | [tag.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/server/saved_objects/tag.ts#:~:text=convertToMultiNamespaceTypeVersion) | - | @@ -1470,12 +1459,12 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion)+ 12 more | - | | | [dependencies_start_mock.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts#:~:text=indexPatterns) | - | | | [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=migrationVersion)+ 78 more | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/filter_group/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/detection_page_filters/index.tsx#:~:text=title), [risk_score_preview_section.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts#:~:text=title)+ 28 more | - | +| | [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/filter_group/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/detection_page_filters/index.tsx#:~:text=title), [risk_score_preview_section.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx#:~:text=title)+ 28 more | - | | | [wrap_search_source_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.ts#:~:text=create) | - | | | [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch) | - | | | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts#:~:text=options) | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/filter_group/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/detection_page_filters/index.tsx#:~:text=title), [risk_score_preview_section.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts#:~:text=title)+ 28 more | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/filter_group/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/detection_page_filters/index.tsx#:~:text=title), [risk_score_preview_section.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts#:~:text=title)+ 9 more | - | +| | [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/filter_group/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/detection_page_filters/index.tsx#:~:text=title), [risk_score_preview_section.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx#:~:text=title)+ 28 more | - | +| | [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_query_filter.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [use_rule_from_timeline.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/filter_group/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/detection_page_filters/index.tsx#:~:text=title), [risk_score_preview_section.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx#:~:text=title)+ 9 more | - | | | [use_update_data_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/sourcerer/use_update_data_view.tsx#:~:text=toMountPoint), [use_update_data_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/sourcerer/use_update_data_view.tsx#:~:text=toMountPoint), [use_update_data_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/sourcerer/use_update_data_view.tsx#:~:text=toMountPoint), [ingest_pipelines.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/explore/containers/risk_score/onboarding/api/ingest_pipelines.ts#:~:text=toMountPoint), [ingest_pipelines.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/explore/containers/risk_score/onboarding/api/ingest_pipelines.ts#:~:text=toMountPoint), [ingest_pipelines.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/explore/containers/risk_score/onboarding/api/ingest_pipelines.ts#:~:text=toMountPoint), [stored_scripts.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/explore/containers/risk_score/onboarding/api/stored_scripts.ts#:~:text=toMountPoint), [stored_scripts.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/explore/containers/risk_score/onboarding/api/stored_scripts.ts#:~:text=toMountPoint), [stored_scripts.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/explore/containers/risk_score/onboarding/api/stored_scripts.ts#:~:text=toMountPoint), [saved_objects.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/explore/containers/risk_score/onboarding/api/saved_objects.ts#:~:text=toMountPoint)+ 5 more | - | | | [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=KibanaThemeProvider), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=KibanaThemeProvider), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=KibanaThemeProvider) | - | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 | @@ -1486,23 +1475,23 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedRowRenderer), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedRowRenderer) | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=BeatFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=BeatFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=BeatFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=BeatFields) | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=BrowserField), [helpers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.ts#:~:text=BrowserField), [helpers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.ts#:~:text=BrowserField), [helpers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.ts#:~:text=BrowserField), [helpers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.ts#:~:text=BrowserField), [columns.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx#:~:text=BrowserField), [columns.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx#:~:text=BrowserField), [enrichment_summary.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/enrichment_summary.tsx#:~:text=BrowserField), [enrichment_summary.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/enrichment_summary.tsx#:~:text=BrowserField), [use_data_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx#:~:text=BrowserField)+ 29 more | - | -| | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields)+ 104 more | - | +| | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields)+ 102 more | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=IndexFieldsStrategyRequest), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyRequest), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyRequest), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyRequest), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=IndexFieldsStrategyRequest), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=IndexFieldsStrategyRequest) | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=IndexFieldsStrategyResponse), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyResponse), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyResponse), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyResponse), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=IndexFieldsStrategyResponse), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=IndexFieldsStrategyResponse) | - | | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/types.ts#:~:text=SimpleSavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/types.ts#:~:text=SimpleSavedObject) | - | | | [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes), [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes) | - | | | [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=SavedObject), [host_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts#:~:text=SavedObject), [user_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts#:~:text=SavedObject), [user_risk_score_dashboards.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts#:~:text=SavedObject) | - | | | [timelines.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings/timelines.ts#:~:text=convertToMultiNamespaceTypeVersion), [notes.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings/notes.ts#:~:text=convertToMultiNamespaceTypeVersion), [pinned_events.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings/pinned_events.ts#:~:text=convertToMultiNamespaceTypeVersion), [legacy_saved_object_mappings.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_saved_object_mappings.ts#:~:text=convertToMultiNamespaceTypeVersion) | - | -| | [policy_hooks.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [policy_hooks.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [api_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/api_client.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [api_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/api_client.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [api_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/api_client.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID)+ 36 more | - | +| | [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [trusted_app_validator.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [trusted_app_validator.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [receiver.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [receiver.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [policy_hooks.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID), [policy_hooks.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_ID)+ 37 more | - | | | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_NAME), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_NAME) | - | | | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts#:~:text=ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION) | - | -| | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/view/utils.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/view/utils.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [service_actions.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/service/service_actions.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [service_actions.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/service/service_actions.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [service_actions.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/service/service_actions.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID)+ 34 more | - | -| | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME) | - | -| | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION) | - | -| | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [host_isolation_exceptions_api_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [host_isolation_exceptions_api_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [host_isolation_exceptions_api_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID)+ 18 more | - | +| | [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [event_filter_validator.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/event_filter_validator.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [event_filter_validator.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/event_filter_validator.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID), [security_lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/telemetry/tasks/security_lists.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_ID)+ 35 more | - | +| | [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_NAME) | - | +| | [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [create_event_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts#:~:text=ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION) | - | +| | [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [host_isolation_exceptions_validator.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/host_isolation_exceptions_validator.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [host_isolation_exceptions_validator.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/host_isolation_exceptions_validator.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID)+ 19 more | - | | | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_NAME), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/host_isolation_exceptions/index.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/host_isolation_exceptions/index.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_NAME) | - | | | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_DESCRIPTION), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/host_isolation_exceptions/index.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/host_isolation_exceptions/index.ts#:~:text=ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_DESCRIPTION) | - | -| | [policy_hooks.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [policy_hooks.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [blocklists_api_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [blocklists_api_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [blocklists_api_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID)+ 16 more | - | +| | [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [lists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [manifest_manager.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [blocklist_validator.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/blocklist_validator.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [blocklist_validator.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/blocklist_validator.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [policy_hooks.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [policy_hooks.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_ID)+ 17 more | - | | | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_NAME), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/blocklists/index.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_NAME), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/blocklists/index.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_NAME) | - | | | [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION), [constants.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/blocklists/index.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/blocklists/index.ts#:~:text=ENDPOINT_BLOCKLISTS_LIST_DESCRIPTION) | - | @@ -1516,14 +1505,6 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ -## serverlessSearch - -| Deprecated API | Reference location(s) | Remove By | -| ---------------|-----------|-----------| -| | [indexing_api.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/serverless_search/public/application/indexing_api.tsx#:~:text=KibanaThemeProvider), [indexing_api.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/serverless_search/public/application/indexing_api.tsx#:~:text=KibanaThemeProvider), [indexing_api.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/serverless_search/public/application/indexing_api.tsx#:~:text=KibanaThemeProvider) | - | - - - ## share | Deprecated API | Reference location(s) | Remove By | @@ -1623,10 +1604,9 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [register_transform_health_rule_type.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/register_transform_health_rule_type.ts#:~:text=alertFactory) | - | -| | [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [es_index_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/services/es_index_service.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [es_index_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/services/es_index_service.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title) | - | -| | [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [es_index_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/services/es_index_service.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [es_index_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/services/es_index_service.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title) | - | -| | [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [es_index_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/services/es_index_service.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title) | - | -| | [toast_notification_text.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx#:~:text=toMountPoint), [toast_notification_text.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx#:~:text=toMountPoint), [step_create_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx#:~:text=toMountPoint), [step_create_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx#:~:text=toMountPoint), [step_create_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx#:~:text=toMountPoint), [step_create_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx#:~:text=toMountPoint), [step_create_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx#:~:text=toMountPoint), [step_details_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx#:~:text=toMountPoint), [step_details_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx#:~:text=toMountPoint), [step_details_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx#:~:text=toMountPoint)+ 19 more | - | +| | [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [use_data_view_exists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [use_data_view_exists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title) | - | +| | [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [use_data_view_exists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [use_data_view_exists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title) | - | +| | [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [use_data_view_exists.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_data_view_exists.ts#:~:text=title), [transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/routes/api/transforms.ts#:~:text=title), [common.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts#:~:text=title) | - | | | [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/app.tsx#:~:text=KibanaThemeProvider), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/app.tsx#:~:text=KibanaThemeProvider), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/app.tsx#:~:text=KibanaThemeProvider) | - | | | [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/services/license.ts#:~:text=license%24) | 8.8.0 | | | [mount_management_section.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/mount_management_section.ts#:~:text=savedObjects) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 4fa8a64ef89ef..96049ce8778e8 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 3d3ba6b96d49c..942d230ccf25f 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.devdocs.json b/api_docs/discover.devdocs.json index 9179225514ff6..13f444604cc4f 100644 --- a/api_docs/discover.devdocs.json +++ b/api_docs/discover.devdocs.json @@ -24,6 +24,188 @@ } ], "interfaces": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomizationService", + "type": "Interface", + "tags": [], + "label": "DiscoverCustomizationService", + "description": [], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomizationService.set", + "type": "Function", + "tags": [], + "label": "set", + "description": [], + "signature": [ + "(customization: ", + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.DiscoverCustomization", + "text": "DiscoverCustomization" + }, + ") => void" + ], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomizationService.set.$1", + "type": "CompoundType", + "tags": [], + "label": "customization", + "description": [], + "signature": [ + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.DiscoverCustomization", + "text": "DiscoverCustomization" + } + ], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomizationService.get$", + "type": "Function", + "tags": [], + "label": "get$", + "description": [], + "signature": [ + "(id: TCustomizationId) => ", + "Observable", + " | Extract<", + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.TopNavCustomization", + "text": "TopNavCustomization" + }, + ", { id: TCustomizationId; }> | Extract<", + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.UnifiedHistogramCustomization", + "text": "UnifiedHistogramCustomization" + }, + ", { id: TCustomizationId; }> | undefined>" + ], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomizationService.get$.$1", + "type": "Uncategorized", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "TCustomizationId" + ], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomizationService.enable", + "type": "Function", + "tags": [], + "label": "enable", + "description": [], + "signature": [ + "(id: \"search_bar\" | \"top_nav\" | \"unified_histogram\") => void" + ], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomizationService.enable.$1", + "type": "CompoundType", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "\"search_bar\" | \"top_nav\" | \"unified_histogram\"" + ], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomizationService.disable", + "type": "Function", + "tags": [], + "label": "disable", + "description": [], + "signature": [ + "(id: \"search_bar\" | \"top_nav\" | \"unified_histogram\") => void" + ], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomizationService.disable.$1", + "type": "CompoundType", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "\"search_bar\" | \"top_nav\" | \"unified_histogram\"" + ], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, { "parentPluginId": "discover", "id": "def-public.DiscoverProfileOptions", @@ -387,6 +569,153 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SearchBarCustomization", + "type": "Interface", + "tags": [], + "label": "SearchBarCustomization", + "description": [], + "path": "src/plugins/discover/public/customizations/customization_types/search_bar_customization.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.SearchBarCustomization.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "\"search_bar\"" + ], + "path": "src/plugins/discover/public/customizations/customization_types/search_bar_customization.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SearchBarCustomization.CustomDataViewPicker", + "type": "CompoundType", + "tags": [], + "label": "CustomDataViewPicker", + "description": [], + "signature": [ + "React.ComponentType<{}> | undefined" + ], + "path": "src/plugins/discover/public/customizations/customization_types/search_bar_customization.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SearchBarCustomization.PrependFilterBar", + "type": "CompoundType", + "tags": [], + "label": "PrependFilterBar", + "description": [], + "signature": [ + "React.ComponentType<{}> | undefined" + ], + "path": "src/plugins/discover/public/customizations/customization_types/search_bar_customization.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SearchBarCustomization.CustomSearchBar", + "type": "CompoundType", + "tags": [], + "label": "CustomSearchBar", + "description": [], + "signature": [ + "React.ComponentType<", + { + "pluginId": "navigation", + "scope": "public", + "docId": "kibNavigationPluginApi", + "section": "def-public.TopNavMenuProps", + "text": "TopNavMenuProps" + }, + "<", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.AggregateQuery", + "text": "AggregateQuery" + }, + ">> | undefined" + ], + "path": "src/plugins/discover/public/customizations/customization_types/search_bar_customization.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "discover", + "id": "def-public.TopNavCustomization", + "type": "Interface", + "tags": [], + "label": "TopNavCustomization", + "description": [], + "path": "src/plugins/discover/public/customizations/customization_types/top_nav_customization.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.TopNavCustomization.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "\"top_nav\"" + ], + "path": "src/plugins/discover/public/customizations/customization_types/top_nav_customization.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.TopNavCustomization.defaultMenu", + "type": "Object", + "tags": [], + "label": "defaultMenu", + "description": [], + "signature": [ + "TopNavDefaultMenu", + " | undefined" + ], + "path": "src/plugins/discover/public/customizations/customization_types/top_nav_customization.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.TopNavCustomization.getMenuItems", + "type": "Function", + "tags": [], + "label": "getMenuItems", + "description": [], + "signature": [ + "(() => ", + "TopNavMenuItem", + "[]) | undefined" + ], + "path": "src/plugins/discover/public/customizations/customization_types/top_nav_customization.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false } ], "enums": [], @@ -433,7 +762,7 @@ "label": "DiscoverContainerProps", "description": [], "signature": [ - "{ overrideServices: Partial<", + "{ isLoading?: boolean | undefined; overrideServices: Partial<", "DiscoverServices", ">; scopedHistory: ", { @@ -443,7 +772,7 @@ "section": "def-common.ScopedHistory", "text": "ScopedHistory" }, - "; customize: ", + "; customizationCallbacks: ", { "pluginId": "discover", "scope": "public", @@ -451,13 +780,50 @@ "section": "def-public.CustomizationCallback", "text": "CustomizationCallback" }, - "; }" + "[]; }" ], "path": "src/plugins/discover/public/components/discover_container/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverCustomization", + "type": "Type", + "tags": [], + "label": "DiscoverCustomization", + "description": [], + "signature": [ + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.SearchBarCustomization", + "text": "SearchBarCustomization" + }, + " | ", + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.TopNavCustomization", + "text": "TopNavCustomization" + }, + " | ", + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.UnifiedHistogramCustomization", + "text": "UnifiedHistogramCustomization" + } + ], + "path": "src/plugins/discover/public/customizations/customization_service.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "discover", "id": "def-public.DiscoverProfileId", @@ -588,6 +954,29 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "discover", + "id": "def-public.UnifiedHistogramCustomization", + "type": "Type", + "tags": [], + "label": "UnifiedHistogramCustomization", + "description": [], + "signature": [ + "UnifiedHistogramCustomizationId & Pick<", + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramContainerProps", + "text": "UnifiedHistogramContainerProps" + }, + ", \"onBrushEnd\" | \"disabledActions\" | \"onFilter\" | \"withDefaultActions\">" + ], + "path": "src/plugins/discover/public/customizations/customization_types/histogram_customization.tsx", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "objects": [], @@ -602,24 +991,6 @@ "deprecated": false, "trackAdoption": false, "children": [ - { - "parentPluginId": "discover", - "id": "def-public.DiscoverSetup.docViews", - "type": "Object", - "tags": [], - "label": "docViews", - "description": [], - "signature": [ - "{ addDocView(docViewRaw: ", - "DocViewInput", - " | ", - "DocViewInputFn", - "): void; }" - ], - "path": "src/plugins/discover/public/plugin.tsx", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "discover", "id": "def-public.DiscoverSetup.locator", @@ -1293,14 +1664,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "exploratoryView", - "path": "x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/hooks/use_discover_link.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_logs_discover_link.tsx" - }, { "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx" @@ -1309,6 +1672,14 @@ "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx" }, + { + "plugin": "exploratoryView", + "path": "x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/hooks/use_discover_link.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_logs_discover_link.tsx" + }, { "plugin": "cloudSecurityPosture", "path": "x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/overview_tab.tsx" diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 0e0dd45ee8c2c..0a25336252232 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.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 | |-------------------|-----------|------------------------|-----------------| -| 79 | 0 | 52 | 15 | +| 98 | 0 | 71 | 15 | ## Client diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index c14275bee0977..426ead75115cc 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-08-25 +date: 2023-09-04 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 fc90807bbf9e0..f29903433c4cd 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.devdocs.json b/api_docs/elastic_assistant.devdocs.json new file mode 100644 index 0000000000000..9a3dd4987b4a5 --- /dev/null +++ b/api_docs/elastic_assistant.devdocs.json @@ -0,0 +1,101 @@ +{ + "id": "elasticAssistant", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [], + "setup": { + "parentPluginId": "elasticAssistant", + "id": "def-server.ElasticAssistantPluginSetup", + "type": "Interface", + "tags": [], + "label": "ElasticAssistantPluginSetup", + "description": [ + "The plugin setup interface" + ], + "path": "x-pack/plugins/elastic_assistant/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "elasticAssistant", + "id": "def-server.ElasticAssistantPluginSetup.actions", + "type": "Object", + "tags": [], + "label": "actions", + "description": [], + "signature": [ + { + "pluginId": "actions", + "scope": "server", + "docId": "kibActionsPluginApi", + "section": "def-server.PluginSetupContract", + "text": "PluginSetupContract" + } + ], + "path": "x-pack/plugins/elastic_assistant/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "setup", + "initialIsOpen": true + }, + "start": { + "parentPluginId": "elasticAssistant", + "id": "def-server.ElasticAssistantPluginStart", + "type": "Interface", + "tags": [], + "label": "ElasticAssistantPluginStart", + "description": [ + "The plugin start interface" + ], + "path": "x-pack/plugins/elastic_assistant/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "elasticAssistant", + "id": "def-server.ElasticAssistantPluginStart.actions", + "type": "Object", + "tags": [], + "label": "actions", + "description": [], + "signature": [ + { + "pluginId": "actions", + "scope": "server", + "docId": "kibActionsPluginApi", + "section": "def-server.PluginStartContract", + "text": "PluginStartContract" + } + ], + "path": "x-pack/plugins/elastic_assistant/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "start", + "initialIsOpen": true + } + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx new file mode 100644 index 0000000000000..cd1bcec03b3fc --- /dev/null +++ b/api_docs/elastic_assistant.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: kibElasticAssistantPluginApi +slug: /kibana-dev-docs/api/elasticAssistant +title: "elasticAssistant" +image: https://source.unsplash.com/400x175/?github +description: API docs for the elasticAssistant plugin +date: 2023-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] +--- +import elasticAssistantObj from './elastic_assistant.devdocs.json'; + +Server APIs for the Elastic AI Assistant + +Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 4 | 0 | 2 | 0 | + +## Server + +### Setup + + +### Start + + diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 4fd1a918773cc..6fa7efd8597d8 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-08-25 +date: 2023-09-04 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 ce01624369c5a..3c5c09c093b5d 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-08-25 +date: 2023-09-04 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 1c78488318819..1935e646d97be 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-08-25 +date: 2023-09-04 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 8b05632422393..e7cfe48901da6 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-08-25 +date: 2023-09-04 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 67b0ab9b0e165..c62e9e2ada9a9 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-08-25 +date: 2023-09-04 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 8e9684b696fd5..61391709eb35f 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index f62a9d818c4c4..c2a604376318c 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-08-25 +date: 2023-09-04 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 6b856de75dd16..8a15802714534 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-08-25 +date: 2023-09-04 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 7db8632ce92fb..0c1e19017339f 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 8c1eeb4acb4d1..f47fa9e877613 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-08-25 +date: 2023-09-04 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 484eafdaf6355..e6d147e061386 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-08-25 +date: 2023-09-04 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 9740fe59cb4ea..9b6ffc281d27f 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-08-25 +date: 2023-09-04 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 fff5da4ec56d6..d848431241b52 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-08-25 +date: 2023-09-04 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 b264d58a42dd0..389e134529495 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-08-25 +date: 2023-09-04 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 139577dde78a2..ba5e1c9e2dbf5 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-08-25 +date: 2023-09-04 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 4e0297f55db0e..5dc08f904ccec 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-08-25 +date: 2023-09-04 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 c17f61cfd2343..e16aabe5884b4 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-08-25 +date: 2023-09-04 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 fcce69d6d4beb..30aa5edb0990f 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-08-25 +date: 2023-09-04 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 c875447fe31dc..be89424ad5dca 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-08-25 +date: 2023-09-04 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 9b89bd0576973..8d4610f3d9758 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-08-25 +date: 2023-09-04 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 80e501013dd02..2b1d1b9e45ecc 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.devdocs.json b/api_docs/expressions.devdocs.json index 8396810919408..8bd5ba8e59463 100644 --- a/api_docs/expressions.devdocs.json +++ b/api_docs/expressions.devdocs.json @@ -6975,6 +6975,20 @@ "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "expressions", + "id": "def-public.Datatable.warning", + "type": "string", + "tags": [], + "label": "warning", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -7499,7 +7513,7 @@ "\nTracks state of execution.\n\n- `not-started` - before .start() method was called.\n- `pending` - immediately after .start() method is called.\n- `result` - when expression execution completed.\n- `error` - when execution failed with error." ], "signature": [ - "\"error\" | \"pending\" | \"not-started\" | \"result\"" + "\"error\" | \"pending\" | \"result\" | \"not-started\"" ], "path": "src/plugins/expressions/common/execution/container.ts", "deprecated": false, @@ -11686,7 +11700,7 @@ "label": "padding", "description": [], "signature": [ - "\"m\" | \"s\" | \"xs\" | \"l\" | \"xl\" | undefined" + "\"m\" | \"s\" | \"l\" | \"xs\" | \"xl\" | undefined" ], "path": "src/plugins/expressions/public/react_expression_renderer/react_expression_renderer.tsx", "deprecated": false, @@ -18368,6 +18382,20 @@ "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "expressions", + "id": "def-server.Datatable.warning", + "type": "string", + "tags": [], + "label": "warning", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -18892,7 +18920,7 @@ "\nTracks state of execution.\n\n- `not-started` - before .start() method was called.\n- `pending` - immediately after .start() method is called.\n- `result` - when expression execution completed.\n- `error` - when execution failed with error." ], "signature": [ - "\"error\" | \"pending\" | \"not-started\" | \"result\"" + "\"error\" | \"pending\" | \"result\" | \"not-started\"" ], "path": "src/plugins/expressions/common/execution/container.ts", "deprecated": false, @@ -30133,6 +30161,20 @@ "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "expressions", + "id": "def-common.Datatable.warning", + "type": "string", + "tags": [], + "label": "warning", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -31189,7 +31231,7 @@ "\nTracks state of execution.\n\n- `not-started` - before .start() method was called.\n- `pending` - immediately after .start() method is called.\n- `result` - when expression execution completed.\n- `error` - when execution failed with error." ], "signature": [ - "\"error\" | \"pending\" | \"not-started\" | \"result\"" + "\"error\" | \"pending\" | \"result\" | \"not-started\"" ], "path": "src/plugins/expressions/common/execution/container.ts", "deprecated": false, @@ -39366,7 +39408,7 @@ }, "[]; meta?: ", "DatatableMeta", - " | undefined; }" + " | undefined; warning?: string | undefined; }" ], "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", "deprecated": false, @@ -39424,7 +39466,7 @@ }, "[]; meta?: ", "DatatableMeta", - " | undefined; }" + " | undefined; warning?: string | undefined; }" ], "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", "deprecated": false, @@ -41815,7 +41857,7 @@ }, " | { [x: string]: any; })[]; type: \"datatable\"; meta?: ", "DatatableMeta", - " | undefined; }>" + " | undefined; warning?: string | undefined; }>" ], "path": "src/plugins/expressions/common/expression_functions/specs/map_column.ts", "deprecated": false, diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 9794743fb4f44..c18720f2f5b20 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.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 | |-------------------|-----------|------------------------|-----------------| -| 2205 | 17 | 1746 | 5 | +| 2208 | 17 | 1749 | 5 | ## Client diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 1a19b33aae10f..813c498f37fd8 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-08-25 +date: 2023-09-04 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 471dcca3931b4..3c121f16099d2 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-08-25 +date: 2023-09-04 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 72dad803af4e0..13612cc6e1bc1 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-08-25 +date: 2023-09-04 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 2a5699895fee8..f01b85e9a890a 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-08-25 +date: 2023-09-04 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 b2a3bf51333a0..2380f57b1afb6 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index d827b0485dc57..f8348e3375fc7 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-08-25 +date: 2023-09-04 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 323575f75cda1..a2f7b9112a0dc 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-08-25 +date: 2023-09-04 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 e6f44f3b28c17..aba3d39086e88 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-08-25 +date: 2023-09-04 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 26e89cfdf5a5e..8fcf0b01b0a00 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-08-25 +date: 2023-09-04 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 2e0681779b06b..108f44c2631fa 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-08-25 +date: 2023-09-04 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 e3fa160e69b3a..6ad91bcb6a5f8 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.devdocs.json b/api_docs/index_management.devdocs.json index 3da3a9bee799e..6d3b01d5245cf 100644 --- a/api_docs/index_management.devdocs.json +++ b/api_docs/index_management.devdocs.json @@ -201,6 +201,48 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "indexManagement", + "id": "def-public.Index.isRollupIndex", + "type": "CompoundType", + "tags": [], + "label": "isRollupIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-public.Index.ilm", + "type": "Object", + "tags": [], + "label": "ilm", + "description": [], + "signature": [ + "{ index: string; managed: boolean; } | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-public.Index.isFollowerIndex", + "type": "CompoundType", + "tags": [], + "label": "isFollowerIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "indexManagement", "id": "def-public.Index.health", @@ -529,6 +571,48 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "indexManagement", + "id": "def-server.Index.isRollupIndex", + "type": "CompoundType", + "tags": [], + "label": "isRollupIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-server.Index.ilm", + "type": "Object", + "tags": [], + "label": "ilm", + "description": [], + "signature": [ + "{ index: string; managed: boolean; } | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-server.Index.isFollowerIndex", + "type": "CompoundType", + "tags": [], + "label": "isFollowerIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "indexManagement", "id": "def-server.Index.health", @@ -1728,6 +1812,48 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "indexManagement", + "id": "def-common.Index.isRollupIndex", + "type": "CompoundType", + "tags": [], + "label": "isRollupIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-common.Index.ilm", + "type": "Object", + "tags": [], + "label": "ilm", + "description": [], + "signature": [ + "{ index: string; managed: boolean; } | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-common.Index.isFollowerIndex", + "type": "CompoundType", + "tags": [], + "label": "isFollowerIndex", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "indexManagement", "id": "def-common.Index.health", diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index cc483d9bc46dc..8ecb81a2bc8b2 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/platform-deployment-management](https://github.com/orgs/elasti | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 182 | 0 | 177 | 4 | +| 191 | 0 | 186 | 4 | ## Client diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 61ba52c929ab3..79873a75bf1b3 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-08-25 +date: 2023-09-04 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 8c801de4dfd54..10eb725db8a7a 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-08-25 +date: 2023-09-04 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 30579ea25fd9f..61cfcd6d71f54 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-08-25 +date: 2023-09-04 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 d5743e191a27e..1fa14fddbbb8c 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-08-25 +date: 2023-09-04 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 21b85ed4c21fe..7efbbe884d5f2 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-08-25 +date: 2023-09-04 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 27534228f4192..724c0c8adb324 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_alerting_api_integration_helpers.devdocs.json new file mode 100644 index 0000000000000..8f4c6849b5061 --- /dev/null +++ b/api_docs/kbn_alerting_api_integration_helpers.devdocs.json @@ -0,0 +1,430 @@ +{ + "id": "@kbn/alerting-api-integration-helpers", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool", + "type": "Class", + "tags": [], + "label": "ESTestIndexTool", + "description": [], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "es", + "description": [], + "signature": [ + "default" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.Unnamed.$2", + "type": "Any", + "tags": [], + "label": "retry", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.Unnamed.$3", + "type": "string", + "tags": [], + "label": "index", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.setup", + "type": "Function", + "tags": [], + "label": "setup", + "description": [], + "signature": [ + "() => Promise<", + "TransportResult", + "<", + "IndicesCreateResponse", + ", unknown>>" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.destroy", + "type": "Function", + "tags": [], + "label": "destroy", + "description": [], + "signature": [ + "() => Promise<", + "TransportResult", + "<", + "IndicesResponseBase", + ", unknown> | undefined>" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.search", + "type": "Function", + "tags": [], + "label": "search", + "description": [], + "signature": [ + "(source: string, reference?: string | undefined) => Promise<", + "TransportResult", + "<", + "SearchResponse", + ">, unknown>>" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.search.$1", + "type": "string", + "tags": [], + "label": "source", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.search.$2", + "type": "string", + "tags": [], + "label": "reference", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.getAll", + "type": "Function", + "tags": [], + "label": "getAll", + "description": [], + "signature": [ + "(size?: number) => Promise<", + "TransportResult", + "<", + "SearchResponse", + ">, unknown>>" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.getAll.$1", + "type": "number", + "tags": [], + "label": "size", + "description": [], + "signature": [ + "number" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.removeAll", + "type": "Function", + "tags": [], + "label": "removeAll", + "description": [], + "signature": [ + "() => Promise<", + "DeleteByQueryResponse", + ">" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.waitForDocs", + "type": "Function", + "tags": [], + "label": "waitForDocs", + "description": [], + "signature": [ + "(source: string, reference: string, numDocs?: number) => Promise" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.waitForDocs.$1", + "type": "string", + "tags": [], + "label": "source", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.waitForDocs.$2", + "type": "string", + "tags": [], + "label": "reference", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ESTestIndexTool.waitForDocs.$3", + "type": "number", + "tags": [], + "label": "numDocs", + "description": [], + "signature": [ + "number" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.getHttpProxyServer", + "type": "Function", + "tags": [], + "label": "getHttpProxyServer", + "description": [], + "signature": [ + "(targetUrl: string, kbnTestServerConfig: any, onProxyResHandler: (proxyRes?: unknown, req?: unknown, res?: unknown) => void) => Promise<", + "node_modules/@types/http-proxy/index", + ">" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/get_proxy_server.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.getHttpProxyServer.$1", + "type": "string", + "tags": [], + "label": "targetUrl", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/get_proxy_server.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.getHttpProxyServer.$2", + "type": "Any", + "tags": [], + "label": "kbnTestServerConfig", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/get_proxy_server.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.getHttpProxyServer.$3", + "type": "Function", + "tags": [], + "label": "onProxyResHandler", + "description": [], + "signature": [ + "(proxyRes?: unknown, req?: unknown, res?: unknown) => void" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/get_proxy_server.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.getProxyPort", + "type": "Function", + "tags": [], + "label": "getProxyPort", + "description": [], + "signature": [ + "(kbnTestServerConfig: any) => number" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/get_proxy_server.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.getProxyPort.$1", + "type": "Any", + "tags": [], + "label": "kbnTestServerConfig", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/get_proxy_server.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/alerting-api-integration-helpers", + "id": "def-common.ES_TEST_INDEX_NAME", + "type": "string", + "tags": [], + "label": "ES_TEST_INDEX_NAME", + "description": [], + "signature": [ + "\".kibana-alerting-test-data\"" + ], + "path": "x-pack/test/alerting_api_integration/packages/helpers/es_test_index_tool.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx new file mode 100644 index 0000000000000..d975f7289f177 --- /dev/null +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnAlertingApiIntegrationHelpersPluginApi +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-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] +--- +import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; + + + +Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 24 | 3 | 24 | 0 | + +## Common + +### Functions + + +### Classes + + +### Consts, variables and types + + diff --git a/api_docs/kbn_alerting_state_types.devdocs.json b/api_docs/kbn_alerting_state_types.devdocs.json index ada44596c7d8f..df8c83dfdc58a 100644 --- a/api_docs/kbn_alerting_state_types.devdocs.json +++ b/api_docs/kbn_alerting_state_types.devdocs.json @@ -114,105 +114,135 @@ }, { "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.AlertInstanceMeta", + "id": "def-common.LatestAlertInstanceMetaSchema", "type": "Type", "tags": [], - "label": "AlertInstanceMeta", + "label": "LatestAlertInstanceMetaSchema", "description": [], "signature": [ - "{ lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; uuid?: string | undefined; }" + "{ readonly uuid?: string | undefined; readonly lastScheduledActions?: Readonly<{ actions?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; readonly flappingHistory?: boolean[] | undefined; readonly flapping?: boolean | undefined; readonly maintenanceWindowIds?: string[] | undefined; readonly pendingRecoveredCount?: number | undefined; }" ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.AlertInstanceState", + "id": "def-common.LatestAlertInstanceStateSchema", "type": "Type", "tags": [], - "label": "AlertInstanceState", + "label": "LatestAlertInstanceStateSchema", "description": [], "signature": [ - "{ [x: string]: unknown; }" + "{ [x: string]: any; }" ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.LastScheduledActions", + "id": "def-common.LatestLastScheduledActionsSchema", "type": "Type", "tags": [], - "label": "LastScheduledActions", + "label": "LatestLastScheduledActionsSchema", "description": [], "signature": [ - "{ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }" + "{ readonly actions?: Record> | undefined; readonly subgroup?: string | undefined; readonly date: string; readonly group: string; }" ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.RawAlertInstance", + "id": "def-common.LatestRawAlertInstanceSchema", "type": "Type", "tags": [], - "label": "RawAlertInstance", + "label": "LatestRawAlertInstanceSchema", "description": [], "signature": [ - "{ state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; uuid?: string | undefined; } | undefined; }" + "{ readonly meta?: Readonly<{ uuid?: string | undefined; lastScheduledActions?: Readonly<{ actions?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; readonly state?: Record | undefined; }" ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.RuleTaskParams", + "id": "def-common.LatestTaskStateSchema", "type": "Type", "tags": [], - "label": "RuleTaskParams", + "label": "LatestTaskStateSchema", "description": [], "signature": [ - "{ alertId: string; } & { spaceId?: string | undefined; }" + "{ readonly alertTypeState?: Record | undefined; readonly alertInstances?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined; readonly alertRecoveredInstances?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined; readonly previousStartedAt?: string | null | undefined; readonly summaryActions?: Record> | undefined; }" ], - "path": "x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.RuleTaskState", + "id": "def-common.LatestThrottledActionSchema", "type": "Type", "tags": [], - "label": "RuleTaskState", + "label": "LatestThrottledActionSchema", "description": [], "signature": [ - "{ alertTypeState?: { [x: string]: unknown; } | undefined; alertInstances?: { [x: string]: { state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; uuid?: string | undefined; } | undefined; }; } | undefined; alertRecoveredInstances?: { [x: string]: { state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; } & { actions?: { [x: string]: { date: Date; }; } | undefined; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; uuid?: string | undefined; } | undefined; }; } | undefined; previousStartedAt?: Date | null | undefined; summaryActions?: { [x: string]: { date: Date; }; } | undefined; }" + "{ [x: string]: Readonly<{} & { date: string; }>; }" ], - "path": "x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.ThrottledActions", + "id": "def-common.MutableLatestAlertInstanceMetaSchema", "type": "Type", "tags": [], - "label": "ThrottledActions", + "label": "MutableLatestAlertInstanceMetaSchema", "description": [], "signature": [ - "{ [x: string]: { date: Date; }; }" + "{ uuid?: Mutable; lastScheduledActions?: Mutable> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined>; flappingHistory?: Mutable; flapping?: Mutable; maintenanceWindowIds?: Mutable; pendingRecoveredCount?: Mutable; }" ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/alerting-state-types", + "id": "def-common.MutableLatestTaskStateSchema", + "type": "Type", + "tags": [], + "label": "MutableLatestTaskStateSchema", + "description": [], + "signature": [ + "{ alertTypeState?: Mutable | undefined>; alertInstances?: Mutable> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined>; alertRecoveredInstances?: Mutable> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined>; previousStartedAt?: Mutable; summaryActions?: Mutable> | undefined>; }" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/alerting-state-types", + "id": "def-common.RuleTaskParams", + "type": "Type", + "tags": [], + "label": "RuleTaskParams", + "description": [], + "signature": [ + "{ alertId: string; } & { spaceId?: string | undefined; }" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -253,78 +283,78 @@ "objects": [ { "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.DateFromString", + "id": "def-common.emptyState", "type": "Object", "tags": [], - "label": "DateFromString", + "label": "emptyState", "description": [], - "signature": [ - "Type", - "" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/date_from_string.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", "deprecated": false, "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.rawAlertInstance", - "type": "Object", - "tags": [], - "label": "rawAlertInstance", - "description": [], - "signature": [ - "PartialC", - "<{ state: ", - "RecordC", - "<", - "StringC", - ", ", - "UnknownC", - ">; meta: ", - "PartialC", - "<{ lastScheduledActions: ", - "IntersectionC", - "<[", - "PartialC", - "<{ subgroup: ", - "StringC", - "; }>, ", - "TypeC", - "<{ group: ", - "StringC", - "; date: ", - "Type", - "; }>, ", - "PartialC", - "<{ actions: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ date: ", - "Type", - "; }>>; }>]>; flappingHistory: ", - "ArrayC", - "<", - "BooleanC", - ">; flapping: ", - "BooleanC", - "; maintenanceWindowIds: ", - "ArrayC", - "<", - "StringC", - ">; pendingRecoveredCount: ", - "NumberC", - "; uuid: ", - "StringC", - "; }>; }>" + "children": [ + { + "parentPluginId": "@kbn/alerting-state-types", + "id": "def-common.emptyState.alertTypeState", + "type": "Object", + "tags": [], + "label": "alertTypeState", + "description": [], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [] + }, + { + "parentPluginId": "@kbn/alerting-state-types", + "id": "def-common.emptyState.alertInstances", + "type": "Object", + "tags": [], + "label": "alertInstances", + "description": [], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [] + }, + { + "parentPluginId": "@kbn/alerting-state-types", + "id": "def-common.emptyState.alertRecoveredInstances", + "type": "Object", + "tags": [], + "label": "alertRecoveredInstances", + "description": [], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [] + }, + { + "parentPluginId": "@kbn/alerting-state-types", + "id": "def-common.emptyState.previousStartedAt", + "type": "Uncategorized", + "tags": [], + "label": "previousStartedAt", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/alerting-state-types", + "id": "def-common.emptyState.summaryActions", + "type": "Object", + "tags": [], + "label": "summaryActions", + "description": [], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [] + } ], - "path": "x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts", - "deprecated": false, - "trackAdoption": false, "initialIsOpen": false }, { @@ -353,138 +383,78 @@ }, { "parentPluginId": "@kbn/alerting-state-types", - "id": "def-common.ruleStateSchema", + "id": "def-common.stateSchemaByVersion", "type": "Object", "tags": [], - "label": "ruleStateSchema", + "label": "stateSchemaByVersion", "description": [], - "signature": [ - "PartialC", - "<{ alertTypeState: ", - "RecordC", - "<", - "StringC", - ", ", - "UnknownC", - ">; alertInstances: ", - "RecordC", - "<", - "StringC", - ", ", - "PartialC", - "<{ state: ", - "RecordC", - "<", - "StringC", - ", ", - "UnknownC", - ">; meta: ", - "PartialC", - "<{ lastScheduledActions: ", - "IntersectionC", - "<[", - "PartialC", - "<{ subgroup: ", - "StringC", - "; }>, ", - "TypeC", - "<{ group: ", - "StringC", - "; date: ", - "Type", - "; }>, ", - "PartialC", - "<{ actions: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ date: ", - "Type", - "; }>>; }>]>; flappingHistory: ", - "ArrayC", - "<", - "BooleanC", - ">; flapping: ", - "BooleanC", - "; maintenanceWindowIds: ", - "ArrayC", - "<", - "StringC", - ">; pendingRecoveredCount: ", - "NumberC", - "; uuid: ", - "StringC", - "; }>; }>>; alertRecoveredInstances: ", - "RecordC", - "<", - "StringC", - ", ", - "PartialC", - "<{ state: ", - "RecordC", - "<", - "StringC", - ", ", - "UnknownC", - ">; meta: ", - "PartialC", - "<{ lastScheduledActions: ", - "IntersectionC", - "<[", - "PartialC", - "<{ subgroup: ", - "StringC", - "; }>, ", - "TypeC", - "<{ group: ", - "StringC", - "; date: ", - "Type", - "; }>, ", - "PartialC", - "<{ actions: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ date: ", - "Type", - "; }>>; }>]>; flappingHistory: ", - "ArrayC", - "<", - "BooleanC", - ">; flapping: ", - "BooleanC", - "; maintenanceWindowIds: ", - "ArrayC", - "<", - "StringC", - ">; pendingRecoveredCount: ", - "NumberC", - "; uuid: ", - "StringC", - "; }>; }>>; previousStartedAt: ", - "UnionC", - "<[", - "NullC", - ", ", - "Type", - "]>; summaryActions: ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ date: ", - "Type", - "; }>>; }>" - ], - "path": "x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts", + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", "deprecated": false, "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerting-state-types", + "id": "def-common.stateSchemaByVersion.1", + "type": "Object", + "tags": [], + "label": "1", + "description": [], + "signature": [ + "{ up: (state: Record) => Readonly<{ alertTypeState?: Record | undefined; alertInstances?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined; alertRecoveredInstances?: Record> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined; previousStartedAt?: string | null | undefined; summaryActions?: Record> | undefined; } & {}>; schema: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ alertTypeState: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + " | undefined>; alertInstances: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined>; alertRecoveredInstances: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "> | undefined; subgroup?: string | undefined; } & { date: string; group: string; }> | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; maintenanceWindowIds?: string[] | undefined; pendingRecoveredCount?: number | undefined; } & {}> | undefined; state?: Record | undefined; } & {}>> | undefined>; previousStartedAt: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; summaryActions: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "> | undefined>; }>; }" + ], + "path": "x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], "initialIsOpen": false } ] diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 62aa35b6507fa..8242e7c2acf60 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.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 | |-------------------|-----------|------------------------|-----------------| -| 16 | 0 | 15 | 0 | +| 23 | 0 | 22 | 0 | ## Common diff --git a/api_docs/kbn_alerts_as_data_utils.devdocs.json b/api_docs/kbn_alerts_as_data_utils.devdocs.json index 01bc8dd24d62c..2d2e9c678ef98 100644 --- a/api_docs/kbn_alerts_as_data_utils.devdocs.json +++ b/api_docs/kbn_alerts_as_data_utils.devdocs.json @@ -19,6 +19,54 @@ "common": { "classes": [], "functions": [ + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.buildAlertFieldsRequest", + "type": "Function", + "tags": [], + "label": "buildAlertFieldsRequest", + "description": [], + "signature": [ + "(fields: string[], excludeEcsData?: boolean | undefined) => { format?: string | undefined; field: string; include_unmapped: boolean; }[]" + ], + "path": "packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.buildAlertFieldsRequest.$1", + "type": "Array", + "tags": [], + "label": "fields", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.buildAlertFieldsRequest.$2", + "type": "CompoundType", + "tags": [], + "label": "excludeEcsData", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/alerts-as-data-utils", "id": "def-common.createSchemaFromFieldMap", @@ -170,6 +218,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.ALERT_EVENTS_FIELDS", + "type": "Array", + "tags": [], + "label": "ALERT_EVENTS_FIELDS", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/kbn-alerts-as-data-utils/src/search/security/fields.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/alerts-as-data-utils", "id": "def-common.AlertFieldMap", diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index adebc82a83740..f1ab6919b6f65 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.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 | |-------------------|-----------|------------------------|-----------------| -| 25 | 0 | 25 | 0 | +| 29 | 0 | 29 | 0 | ## Common diff --git a/api_docs/kbn_alerts_ui_shared.devdocs.json b/api_docs/kbn_alerts_ui_shared.devdocs.json index 77aa446d1ecfb..a63af81c30848 100644 --- a/api_docs/kbn_alerts_ui_shared.devdocs.json +++ b/api_docs/kbn_alerts_ui_shared.devdocs.json @@ -19,6 +19,39 @@ "common": { "classes": [], "functions": [ + { + "parentPluginId": "@kbn/alerts-ui-shared", + "id": "def-common.AddMessageVariables", + "type": "Function", + "tags": [], + "label": "AddMessageVariables", + "description": [], + "signature": [ + "({ buttonTitle, messageVariables, paramsProperty, onSelectEventHandler, showButtonTitle, }: React.PropsWithChildren) => JSX.Element" + ], + "path": "packages/kbn-alerts-ui-shared/src/add_message_variables/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerts-ui-shared", + "id": "def-common.AddMessageVariables.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n buttonTitle,\n messageVariables,\n paramsProperty,\n onSelectEventHandler,\n showButtonTitle = false,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren" + ], + "path": "packages/kbn-alerts-ui-shared/src/add_message_variables/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/alerts-ui-shared", "id": "def-common.AlertLifecycleStatusBadge", diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 8c74e1ae6cfa2..f577d11e536eb 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.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 | |-------------------|-----------|------------------------|-----------------| -| 8 | 0 | 7 | 1 | +| 10 | 0 | 9 | 1 | ## Common diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 538a54ebba2ee..370cb8139cc91 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.devdocs.json b/api_docs/kbn_analytics_client.devdocs.json index 28f854cfa8f5f..08169d4866da6 100644 --- a/api_docs/kbn_analytics_client.devdocs.json +++ b/api_docs/kbn_analytics_client.devdocs.json @@ -710,6 +710,22 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" + }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts" @@ -742,22 +758,6 @@ "plugin": "globalSearchBar", "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" @@ -1304,6 +1304,10 @@ "plugin": "@kbn/core-analytics-server-internal", "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" }, + { + "plugin": "licensing", + "path": "x-pack/plugins/licensing/common/register_analytics_context_provider.ts" + }, { "plugin": "@kbn/core-application-browser-internal", "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.ts" @@ -1348,21 +1352,17 @@ "plugin": "cloud", "path": "x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts" }, - { - "plugin": "licensing", - "path": "x-pack/plugins/licensing/common/register_analytics_context_provider.ts" - }, { "plugin": "security", "path": "x-pack/plugins/security/public/analytics/register_user_context.ts" }, { "plugin": "telemetry", - "path": "src/plugins/telemetry/server/plugin.ts" + "path": "src/plugins/telemetry/public/plugin.ts" }, { "plugin": "telemetry", - "path": "src/plugins/telemetry/public/plugin.ts" + "path": "src/plugins/telemetry/server/plugin.ts" }, { "plugin": "securitySolution", diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 9f7f924732877..d66ce94813eef 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 1b8a7a36f1bad..cf22afd96fb91 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-08-25 +date: 2023-09-04 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 fa6f13d11b57b..7d196f38a5467 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-08-25 +date: 2023-09-04 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 d41870abea090..e3cf58c6a9112 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-08-25 +date: 2023-09-04 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 b6e9c9c0e1654..bb66ecdcd9c59 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-08-25 +date: 2023-09-04 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 26d0b8ce51931..99d0cd8f8fed6 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-08-25 +date: 2023-09-04 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 febb3cc742132..8ca9f2bf46952 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-08-25 +date: 2023-09-04 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 258b0d490036d..2a9e42159a863 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index 071fa91e1f370..087efd0ed1b3a 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-08-25 +date: 2023-09-04 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 4706abf4d2e4b..a688b4bb11ac0 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-08-25 +date: 2023-09-04 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 f0c425f771a36..0ec80a6d5b9a1 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-08-25 +date: 2023-09-04 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 5502673d5fb2e..eb47b8ad31282 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-08-25 +date: 2023-09-04 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 2ff3dcd95091f..b5974c758f75b 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-08-25 +date: 2023-09-04 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 4e33825dffc4a..5722513733587 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-08-25 +date: 2023-09-04 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 24789aea7433c..1ad780440ef49 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-08-25 +date: 2023-09-04 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 6abf138cdf530..7b4e6f8248423 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-08-25 +date: 2023-09-04 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 e0c0d052092d8..c69c2e0efb03a 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-08-25 +date: 2023-09-04 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 be1bf98e73fae..877836f928464 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-08-25 +date: 2023-09-04 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 834183af04a2a..67456e908f329 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_code_editor.devdocs.json index 97a003dc517d0..eea9517c0bb23 100644 --- a/api_docs/kbn_code_editor.devdocs.json +++ b/api_docs/kbn_code_editor.devdocs.json @@ -27,7 +27,7 @@ "label": "CodeEditor", "description": [], "signature": [ - "({ languageId, value, onChange, width, options, overrideEditorWillMount, editorDidMount, editorWillMount, useDarkTheme: useDarkThemeProp, transparentBackground, suggestionProvider, signatureProvider, hoverProvider, placeholder, languageConfiguration, \"aria-label\": ariaLabel, isCopyable, allowFullScreen, }: React.PropsWithChildren<", + "({ languageId, value, onChange, width, height, options, overrideEditorWillMount, editorDidMount, editorWillMount, useDarkTheme: useDarkThemeProp, transparentBackground, suggestionProvider, signatureProvider, hoverProvider, placeholder, languageConfiguration, \"aria-label\": ariaLabel, isCopyable, allowFullScreen, }: React.PropsWithChildren<", "Props", ">) => JSX.Element" ], @@ -40,7 +40,7 @@ "id": "def-common.CodeEditor.$1", "type": "CompoundType", "tags": [], - "label": "{\n languageId,\n value,\n onChange,\n width,\n options,\n overrideEditorWillMount,\n editorDidMount,\n editorWillMount,\n useDarkTheme: useDarkThemeProp,\n transparentBackground,\n suggestionProvider,\n signatureProvider,\n hoverProvider,\n placeholder,\n languageConfiguration,\n 'aria-label': ariaLabel = i18n.translate('sharedUXPackages.codeEditor.ariaLabel', {\n defaultMessage: 'Code Editor',\n }),\n isCopyable = false,\n allowFullScreen = false,\n}", + "label": "{\n languageId,\n value,\n onChange,\n width,\n height = '100px',\n options,\n overrideEditorWillMount,\n editorDidMount,\n editorWillMount,\n useDarkTheme: useDarkThemeProp,\n transparentBackground,\n suggestionProvider,\n signatureProvider,\n hoverProvider,\n placeholder,\n languageConfiguration,\n 'aria-label': ariaLabel = i18n.translate('sharedUXPackages.codeEditor.ariaLabel', {\n defaultMessage: 'Code Editor',\n }),\n isCopyable = false,\n allowFullScreen = false,\n}", "description": [], "signature": [ "React.PropsWithChildren<", diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index c935fe4b330f5..e674268e68dda 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mocks.mdx b/api_docs/kbn_code_editor_mocks.mdx index fe9e5db564947..d352e9cfabe5d 100644 --- a/api_docs/kbn_code_editor_mocks.mdx +++ b/api_docs/kbn_code_editor_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mocks title: "@kbn/code-editor-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mocks plugin -date: 2023-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mocks'] --- import kbnCodeEditorMocksObj from './kbn_code_editor_mocks.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index e5f0aa0a43331..6ff576e59d157 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-08-25 +date: 2023-09-04 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 d6bbe14444703..e9ad3de74572b 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.devdocs.json b/api_docs/kbn_config_mocks.devdocs.json index df37ecf488422..29e17d6500043 100644 --- a/api_docs/kbn_config_mocks.devdocs.json +++ b/api_docs/kbn_config_mocks.devdocs.json @@ -344,7 +344,15 @@ "section": "def-common.ChangedDeprecatedPaths", "text": "ChangedDeprecatedPaths" }, - ">, [], unknown>; } & ", + ">, [], unknown>; addDynamicConfigPaths: jest.MockInstance; setDynamicConfigOverrides: jest.MockInstance], unknown>; } & ", "IConfigService" ], "path": "packages/kbn-config-mocks/src/config_service.mock.ts", diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 3b18e8f265c03..27b92aed9ea81 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-08-25 +date: 2023-09-04 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 0e27b4b95029c..2b52f0f89b0c5 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-08-25 +date: 2023-09-04 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 35b859dad93af..0cb6092fc11c5 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-08-25 +date: 2023-09-04 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 422f96ad9320d..df613465fd570 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-08-25 +date: 2023-09-04 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 fb7e5fd0ee3bb..4bf87ecf7ee57 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-08-25 +date: 2023-09-04 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 648bd95791ea6..676bde7a24187 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-08-25 +date: 2023-09-04 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 4976e93491a80..9be12944b9366 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-08-25 +date: 2023-09-04 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 cba76f2dcffca..2c49f41ead08a 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-08-25 +date: 2023-09-04 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 f86a1bbbe9ca2..75d12c6263985 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-08-25 +date: 2023-09-04 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 009c03838ffa3..570c909999a4a 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-08-25 +date: 2023-09-04 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 91cf5bf6eb0b7..8ce2ce5462df3 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-08-25 +date: 2023-09-04 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 d6b2e270dca90..8993cc4c3bce9 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-08-25 +date: 2023-09-04 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 adc9d19965bab..b5bba31a21c2e 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-08-25 +date: 2023-09-04 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 dc746cb69df68..956f744cdaccd 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-08-25 +date: 2023-09-04 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 f3f2775ac8395..6d7e885eece98 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-08-25 +date: 2023-09-04 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 d8d4c86747f3e..2ce73bbe29934 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-08-25 +date: 2023-09-04 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 e6d2fbacc870a..3821b06a8873d 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-08-25 +date: 2023-09-04 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 f60485208b359..2db3eee5ea8bd 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-08-25 +date: 2023-09-04 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 47e267452b251..d85074be38e63 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_core_apps_server_internal.devdocs.json index 56bb924457859..db65fdba1b5be 100644 --- a/api_docs/kbn_core_apps_server_internal.devdocs.json +++ b/api_docs/kbn_core_apps_server_internal.devdocs.json @@ -159,7 +159,23 @@ ], "interfaces": [], "enums": [], - "misc": [], + "misc": [ + { + "parentPluginId": "@kbn/core-apps-server-internal", + "id": "def-common.CoreAppConfigType", + "type": "Type", + "tags": [], + "label": "CoreAppConfigType", + "description": [], + "signature": [ + "{ readonly allowDynamicConfigOverrides: boolean; }" + ], + "path": "packages/core/apps/core-apps-server-internal/src/core_app_config.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], "objects": [] } } \ No newline at end of file diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 0fe29eeef5d71..8da85febc7332 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; @@ -21,10 +21,13 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 8 | 0 | 8 | 1 | +| 9 | 0 | 9 | 1 | ## Common ### Functions +### Consts, variables and types + + diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 2b9ad3da50248..9382fb2606345 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-08-25 +date: 2023-09-04 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 2adf7df0aa173..8e8431edcd670 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-08-25 +date: 2023-09-04 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 ec2eb34b846a9..271187cab6b21 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-08-25 +date: 2023-09-04 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 cde7296ace982..d1fb8f7ac0c69 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-08-25 +date: 2023-09-04 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 69f1ad940c272..6bbcdd8d1bb52 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-08-25 +date: 2023-09-04 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 9b8a1d2f0d764..b57d8536e8b6d 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-08-25 +date: 2023-09-04 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 7fd4b045f03fa..94f756a9119fe 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-08-25 +date: 2023-09-04 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 3920346a4243e..3d6ff7ee0215f 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-08-25 +date: 2023-09-04 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 755beb9efe3d2..03b58b44714b3 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-08-25 +date: 2023-09-04 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 cda87e5cd8fc1..44d07b498019a 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-08-25 +date: 2023-09-04 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 0a157d961f9e4..f50ee59bc0f94 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-08-25 +date: 2023-09-04 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 6232dc5e40441..3852c645fb4f3 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-08-25 +date: 2023-09-04 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 df5adb00de84b..ca5721a124cc6 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-08-25 +date: 2023-09-04 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 4eb270bee6c25..d67e708675b28 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-08-25 +date: 2023-09-04 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 90a66294358d7..61b38e0d6ac4e 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-08-25 +date: 2023-09-04 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 c104738bfa3bd..b48f4b73db5b3 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-08-25 +date: 2023-09-04 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 2adcc8d45efa9..4bc3a145f71a3 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-08-25 +date: 2023-09-04 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 4790fdbbeab8e..7fc4365e8a5a6 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-08-25 +date: 2023-09-04 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 e531c047377ac..38a4c608985e3 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-08-25 +date: 2023-09-04 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 50bc8402f2577..f76dca5017a24 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-08-25 +date: 2023-09-04 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 a10d8d2f5b89e..0c456c56d9f9a 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-08-25 +date: 2023-09-04 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 3057248e76947..0031424b9247a 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-08-25 +date: 2023-09-04 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 910c8b2905e9d..ab9b0657e001a 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-08-25 +date: 2023-09-04 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 094a32a229a17..d3621a3a7777a 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-08-25 +date: 2023-09-04 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 302d753277e36..a7e10ea28f3bd 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-08-25 +date: 2023-09-04 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 60fb71116616c..b28811d5ca6cf 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-08-25 +date: 2023-09-04 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 00f0934a6ca50..2fdfb865b5e4c 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-08-25 +date: 2023-09-04 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 bc7816013f60c..3af9ba26939ff 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-08-25 +date: 2023-09-04 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 113bd4033166c..0773cd58c9668 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-08-25 +date: 2023-09-04 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 254c417e523c5..3a602d7e7e396 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-08-25 +date: 2023-09-04 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 98139abe86dfa..42034d6fadda2 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-08-25 +date: 2023-09-04 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 6ddcc2349c5b3..b926e48892b73 100644 --- a/api_docs/kbn_core_elasticsearch_server.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server.devdocs.json @@ -68,6 +68,35 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-common.ElasticsearchCapabilities", + "type": "Interface", + "tags": [], + "label": "ElasticsearchCapabilities", + "description": [ + "\nRepresent the capabilities supported by a given ES cluster.\n" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-common.ElasticsearchCapabilities.serverless", + "type": "boolean", + "tags": [], + "label": "serverless", + "description": [ + "\nIndicates whether we're connected to a serverless version of elasticsearch.\nRequired because some options aren't working for serverless and code needs to have the info to react accordingly." + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-elasticsearch-server", "id": "def-common.ElasticsearchClientConfig", @@ -856,6 +885,31 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-common.ElasticsearchServiceStart.getCapabilities", + "type": "Function", + "tags": [], + "label": "getCapabilities", + "description": [ + "\nReturns the capabilities for the default cluster." + ], + "signature": [ + "() => ", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + } + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index df77febd4126a..7ef326189216a 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 108 | 0 | 54 | 0 | +| 111 | 0 | 54 | 0 | ## Common diff --git a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json index 02c0c4b3fb2a5..86657554ce3ed 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json @@ -1494,6 +1494,17 @@ "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server-internal", + "id": "def-common.ClusterInfo.cluster_build_flavor", + "type": "string", + "tags": [], + "label": "cluster_build_flavor", + "description": [], + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index e91aa817ebed7..b70300e61456e 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 37 | 0 | 33 | 3 | +| 38 | 0 | 34 | 3 | ## Common diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.devdocs.json b/api_docs/kbn_core_elasticsearch_server_mocks.devdocs.json index ce0361d169a13..45ce3bb04cd1e 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server_mocks.devdocs.json @@ -19,124 +19,7 @@ "common": { "classes": [], "functions": [], - "interfaces": [ - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart", - "type": "Interface", - "tags": [], - "label": "MockedElasticSearchServiceStart", - "description": [], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart.client", - "type": "Object", - "tags": [], - "label": "client", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-elasticsearch-client-server-mocks", - "scope": "common", - "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-common.ClusterClientMock", - "text": "ClusterClientMock" - } - ], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart.createClient", - "type": "Function", - "tags": [], - "label": "createClient", - "description": [], - "signature": [ - "jest.MockInstance<", - { - "pluginId": "@kbn/core-elasticsearch-client-server-mocks", - "scope": "common", - "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-common.CustomClusterClientMock", - "text": "CustomClusterClientMock" - }, - ", [type: string, config?: Partial<", - { - "pluginId": "@kbn/core-elasticsearch-server", - "scope": "common", - "docId": "kibKbnCoreElasticsearchServerPluginApi", - "section": "def-common.ElasticsearchClientConfig", - "text": "ElasticsearchClientConfig" - }, - "> | undefined], unknown> & ((type: string, config?: Partial<", - { - "pluginId": "@kbn/core-elasticsearch-server", - "scope": "common", - "docId": "kibKbnCoreElasticsearchServerPluginApi", - "section": "def-common.ElasticsearchClientConfig", - "text": "ElasticsearchClientConfig" - }, - "> | undefined) => ", - { - "pluginId": "@kbn/core-elasticsearch-client-server-mocks", - "scope": "common", - "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-common.CustomClusterClientMock", - "text": "CustomClusterClientMock" - }, - ")" - ], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart.createClient.$1", - "type": "string", - "tags": [], - "label": "type", - "description": [], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-elasticsearch-server-mocks", - "id": "def-common.MockedElasticSearchServiceStart.createClient.$2", - "type": "Object", - "tags": [], - "label": "config", - "description": [], - "signature": [ - "Partial<", - { - "pluginId": "@kbn/core-elasticsearch-server", - "scope": "common", - "docId": "kibKbnCoreElasticsearchServerPluginApi", - "section": "def-common.ElasticsearchClientConfig", - "text": "ElasticsearchClientConfig" - }, - "> | undefined" - ], - "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "initialIsOpen": false - } - ], + "interfaces": [], "enums": [], "misc": [ { @@ -173,6 +56,61 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server-mocks", + "id": "def-common.MockedElasticSearchServiceStart", + "type": "Type", + "tags": [], + "label": "MockedElasticSearchServiceStart", + "description": [], + "signature": [ + "{ getCapabilities: jest.MockInstance<", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + }, + ", [], unknown>; } & Omit<", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchServiceStart", + "text": "ElasticsearchServiceStart" + }, + ", \"client\" | \"createClient\"> & { client: ", + { + "pluginId": "@kbn/core-elasticsearch-client-server-mocks", + "scope": "common", + "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", + "section": "def-common.ClusterClientMock", + "text": "ClusterClientMock" + }, + "; createClient: jest.MockedFunction<(type: string, config?: Partial<", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchClientConfig", + "text": "ElasticsearchClientConfig" + }, + "> | undefined) => ", + { + "pluginId": "@kbn/core-elasticsearch-client-server-mocks", + "scope": "common", + "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", + "section": "def-common.CustomClusterClientMock", + "text": "CustomClusterClientMock" + }, + ">; }" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "objects": [ @@ -320,6 +258,52 @@ "returnComment": [], "children": [] }, + { + "parentPluginId": "@kbn/core-elasticsearch-server-mocks", + "id": "def-common.elasticsearchServiceMock.createCapabilities", + "type": "Function", + "tags": [], + "label": "createCapabilities", + "description": [], + "signature": [ + "(parts?: Partial<", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + }, + ">) => ", + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + } + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-elasticsearch-server-mocks", + "id": "def-common.elasticsearchServiceMock.createCapabilities.$1", + "type": "Object", + "tags": [], + "label": "parts", + "description": [], + "signature": [ + "{ serverless?: boolean | undefined; }" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, { "parentPluginId": "@kbn/core-elasticsearch-server-mocks", "id": "def-common.elasticsearchServiceMock.Unnamed", diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index d0565fe62bc08..eca0fde0c364f 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; @@ -21,16 +21,13 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 15 | 1 | 15 | 0 | +| 13 | 1 | 13 | 0 | ## Common ### Objects -### Interfaces - - ### Consts, variables and types diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 5776bc1f70635..2da61fde35f5c 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-08-25 +date: 2023-09-04 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 f39d6e066bf85..eda6107175403 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-08-25 +date: 2023-09-04 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 7e377d3cb6b32..2f1d09bf053d8 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-08-25 +date: 2023-09-04 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 e3c49dfae1a8d..2d0c8efcef163 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-08-25 +date: 2023-09-04 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 34fa9cc274b16..d146cba7023c9 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-08-25 +date: 2023-09-04 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 282b6c8d4a2b9..a639084ea937e 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-08-25 +date: 2023-09-04 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 8d872bba6beb6..07d495610bce4 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-08-25 +date: 2023-09-04 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 b43f3adf91ffa..6b24b9c9e3b62 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-08-25 +date: 2023-09-04 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 6f4246d3463b6..9e425385254f0 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-08-25 +date: 2023-09-04 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 706a791f62076..bb5c8cd6748a8 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-08-25 +date: 2023-09-04 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 b00298efd88f2..188ad7b4882e8 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-08-25 +date: 2023-09-04 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 ced131a6899d7..6f1bf06a0a302 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-08-25 +date: 2023-09-04 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 94e920dae4f2b..53df315ec41aa 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-08-25 +date: 2023-09-04 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 6a072c78cce1f..a914dee17961c 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-08-25 +date: 2023-09-04 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 4a6878a00054d..eec0a8a98e385 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-08-25 +date: 2023-09-04 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 49bd5df3bcb6e..6ea9c339be021 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-08-25 +date: 2023-09-04 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 6ce85cd372a65..9862b3cc1826f 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-08-25 +date: 2023-09-04 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 cacfda54be92b..f50455cc65e96 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-08-25 +date: 2023-09-04 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 1ed0f2d33a14e..f6e4bef97c16c 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-08-25 +date: 2023-09-04 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 9d2d5d394874e..43645a080cfc4 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-08-25 +date: 2023-09-04 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 c316759aa324c..eab6419744a55 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-08-25 +date: 2023-09-04 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 848f667e2797a..66154e1e75516 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-08-25 +date: 2023-09-04 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 df73329dbcce6..646cf9fd1bb02 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -3319,6 +3319,18 @@ "plugin": "usageCollection", "path": "src/plugins/usage_collection/server/routes/stats/stats.ts" }, + { + "plugin": "taskManager", + "path": "x-pack/plugins/task_manager/server/routes/health.ts" + }, + { + "plugin": "taskManager", + "path": "x-pack/plugins/task_manager/server/routes/background_task_utilization.ts" + }, + { + "plugin": "taskManager", + "path": "x-pack/plugins/task_manager/server/routes/metrics.ts" + }, { "plugin": "licensing", "path": "x-pack/plugins/licensing/server/routes/info.ts" @@ -3359,18 +3371,6 @@ "plugin": "spaces", "path": "x-pack/plugins/spaces/server/routes/api/internal/get_active_space.ts" }, - { - "plugin": "taskManager", - "path": "x-pack/plugins/task_manager/server/routes/health.ts" - }, - { - "plugin": "taskManager", - "path": "x-pack/plugins/task_manager/server/routes/background_task_utilization.ts" - }, - { - "plugin": "taskManager", - "path": "x-pack/plugins/task_manager/server/routes/metrics.ts" - }, { "plugin": "security", "path": "x-pack/plugins/security/server/routes/anonymous_access/get_capabilities.ts" @@ -3477,11 +3477,11 @@ }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/get.ts" + "path": "x-pack/plugins/actions/server/routes/connector/list_types/list_types.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/connector_types.ts" + "path": "x-pack/plugins/actions/server/routes/get.ts" }, { "plugin": "actions", @@ -3623,6 +3623,30 @@ "plugin": "ruleRegistry", "path": "x-pack/plugins/rule_registry/server/routes/get_aad_fields_by_rule_type.ts" }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/server/routes/tags/get_all_tags.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/server/routes/tags/get_tag.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/server/routes/assignments/find_assignable_objects.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/server/routes/assignments/get_assignable_types.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/server/routes/internal/find_tags.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + }, { "plugin": "guidedOnboarding", "path": "src/plugins/guided_onboarding/server/routes/guide_state_routes.ts" @@ -3636,40 +3660,80 @@ "path": "src/plugins/guided_onboarding/server/routes/config_routes.ts" }, { - "plugin": "observability", - "path": "x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/route.ts" }, { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/server/routes/health.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/find_exception_references/route.ts" }, { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/server/routes/config.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/read_index_route.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/server/routes/tags/get_all_tags.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/server/routes/tags/get_tag.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/server/routes/assignments/find_assignable_objects.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/get_timeline/index.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/server/routes/assignments/get_assignable_types.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/get_timelines/index.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/server/routes/internal/find_tags.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/draft_timelines/get_draft_timelines/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/telemetry/telemetry_detection_rules_preview_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/read_alerts_index_exists_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_dev_tool_content/routes/read_prebuilt_dev_tool_content_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/index_status/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/tags/routes/get_tags_by_name.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_status_route.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts" + }, + { + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/server/routes/health.ts" + }, + { + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/server/routes/config.ts" }, { "plugin": "visTypeTimeseries", @@ -4307,62 +4371,6 @@ "plugin": "licenseManagement", "path": "x-pack/plugins/license_management/server/routes/api/license/register_start_trial_routes.ts" }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/find_endpoint_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/find_exception_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_item/find_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_index/find_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/internal/find_lists_by_size_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/read_endpoint_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/read_exception_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/read_exception_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_index/read_list_index_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_item/read_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list/read_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_privileges/read_list_privileges_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/summary_exception_list_route.ts" - }, { "plugin": "logstash", "path": "x-pack/plugins/logstash/server/routes/cluster/load.ts" @@ -4395,70 +4403,6 @@ "plugin": "rollup", "path": "x-pack/plugins/rollup/server/routes/api/jobs/register_get_route.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/find_exception_references/route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/read_index_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/get_signals_migration_status_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/get_timeline/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/get_timelines/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/draft_timelines/get_draft_timelines/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/telemetry/telemetry_detection_rules_preview_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/read_alerts_index_exists_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_dev_tool_content/routes/read_prebuilt_dev_tool_content_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/index_status/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/tags/routes/get_tags_by_name.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_status_route.ts" - }, { "plugin": "serverlessSearch", "path": "x-pack/plugins/serverless_search/server/routes/api_key_routes.ts" @@ -4824,24 +4768,208 @@ "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "@kbn/core-http-router-server-mocks", - "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/types.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/connector_types.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/connector_types.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/connector_types.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/connector_types.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/data_streams/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/setup/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/settings/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/app/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/uninstall_token/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/uninstall_token/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.test.ts" + }, + { + "plugin": "@kbn/core-http-router-server-mocks", + "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts" }, { "plugin": "actions", @@ -5031,6 +5159,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" + }, { "plugin": "features", "path": "x-pack/plugins/features/server/routes/index.test.ts" @@ -5423,6 +5555,22 @@ "plugin": "actions", "path": "x-pack/plugins/actions/server/routes/connector/get_all/get_all.test.ts" }, + { + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/connector/list_types/list_types.test.ts" + }, + { + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/connector/list_types/list_types.test.ts" + }, + { + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/connector/list_types/list_types.test.ts" + }, + { + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/connector/list_types/list_types.test.ts" + }, { "plugin": "crossClusterReplication", "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/auto_follow_pattern/register_fetch_route.test.ts" @@ -5576,260 +5724,60 @@ "path": "packages/core/rendering/core-rendering-server-internal/src/bootstrap/register_bootstrap_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/types.ts" + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/server/test/helpers/router_mock.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.test.ts" }, { "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/anonymous_access/get_capabilities.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/anonymous_access/get_state.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/api_keys/enabled.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/api_keys/get.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/authentication/index.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/indices/get_fields.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/role_mapping/get.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/role_mapping/get.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/role_mapping/get.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/data_streams/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/setup/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/output/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/output/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/settings/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/app/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/uninstall_token/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/uninstall_token/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.test.ts" - }, - { - "plugin": "indexManagement", - "path": "x-pack/plugins/index_management/server/test/helpers/router_mock.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.test.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/anonymous_access/get_capabilities.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/anonymous_access/get_state.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/api_keys/enabled.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/api_keys/get.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/authentication/index.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/indices/get_fields.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/role_mapping/get.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/role_mapping/get.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/role_mapping/get.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/role_mapping/get.test.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/role_mapping/get.test.ts" }, { "plugin": "security", @@ -6281,6 +6229,10 @@ "plugin": "encryptedSavedObjects", "path": "x-pack/plugins/encrypted_saved_objects/server/routes/key_rotation.ts" }, + { + "plugin": "serverless", + "path": "x-pack/plugins/serverless/server/plugin.ts" + }, { "plugin": "actions", "path": "x-pack/plugins/actions/server/routes/get_oauth_access_token.ts" @@ -6461,26 +6413,6 @@ "plugin": "ruleRegistry", "path": "x-pack/plugins/rule_registry/server/routes/get_alert_summary.ts" }, - { - "plugin": "observability", - "path": "x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts" - }, - { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/server/data/routes/time_series_query.ts" - }, - { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/server/data/routes/fields.ts" - }, - { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/server/data/routes/indices.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/server/routes/job_service.ts" - }, { "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/server/routes/tags/create_tag.ts" @@ -6502,36 +6434,164 @@ "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, { - "plugin": "visTypeTimeseries", - "path": "src/plugins/vis_types/timeseries/server/routes/vis.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/create_timelines/index.ts" }, { - "plugin": "infra", - "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/import_timelines/index.ts" }, { - "plugin": "profiling", - "path": "x-pack/plugins/profiling/server/routes/setup.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts" }, { - "plugin": "assetManager", - "path": "x-pack/plugins/asset_manager/server/routes/sample_assets.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/server/routes/job_service.ts" }, { - "plugin": "reporting", - "path": "x-pack/plugins/reporting/server/routes/internal/diagnostic/browser.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/api/create_legacy_notification/route.ts" }, { - "plugin": "reporting", - "path": "x-pack/plugins/reporting/server/routes/internal/generate/csv_searchsource_immediate.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts" }, { - "plugin": "reporting", - "path": "x-pack/plugins/reporting/server/routes/internal/generate/generate_from_jobparams.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/create_rule_exceptions/route.ts" }, { - "plugin": "reporting", - "path": "x-pack/plugins/reporting/server/routes/public/generate_from_jobparams.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/export_timelines/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/draft_timelines/clean_draft_timelines/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/indices/delete_indices_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/routes/create_prebuilt_saved_objects.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/routes/delete_prebuilt_saved_objects.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/onboarding/routes/install_risk_scores.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/exceptions/api/manage_exceptions/route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/dashboards/routes/get_dashboards_by_tags.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_score_preview_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_init_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_enable_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_disable_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_score_calculation_route.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts" + }, + { + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/server/data/routes/time_series_query.ts" + }, + { + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/server/data/routes/fields.ts" + }, + { + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/server/data/routes/indices.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/routes/vis.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, + { + "plugin": "profiling", + "path": "x-pack/plugins/profiling/server/routes/setup.ts" + }, + { + "plugin": "assetManager", + "path": "x-pack/plugins/asset_manager/server/routes/sample_assets.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/routes/internal/diagnostic/browser.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/routes/internal/generate/csv_searchsource_immediate.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/routes/internal/generate/generate_from_jobparams.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/routes/public/generate_from_jobparams.ts" }, { "plugin": "indexManagement", @@ -6621,6 +6681,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.ts" + }, { "plugin": "globalSearch", "path": "x-pack/plugins/global_search/server/routes/find.ts" @@ -6997,62 +7061,6 @@ "plugin": "licenseManagement", "path": "x-pack/plugins/license_management/server/routes/api/license/register_permissions_route.ts" }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/create_endpoint_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/create_endpoint_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/create_exception_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/create_exception_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_index/create_list_index_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_item/create_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list/create_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/duplicate_exception_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/export_exception_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_index/export_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/internal/create_exception_filter_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/import_exceptions_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list/import_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/internal/create_exceptions_list_route.ts" - }, { "plugin": "logstash", "path": "x-pack/plugins/logstash/server/routes/pipelines/delete.ts" @@ -7102,184 +7110,72 @@ "path": "x-pack/plugins/searchprofiler/server/routes/profile.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/api/create_legacy_notification/route.ts" + "plugin": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts" + "plugin": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/snapshots.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/create_timelines/index.ts" + "plugin": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/restore.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/import_timelines/index.ts" + "plugin": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/policy.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts" + "plugin": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/policy.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/create_rule_exceptions/route.ts" + "plugin": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/policy.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts" + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/server/server.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/export_timelines/index.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/update_index_settings.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/draft_timelines/clean_draft_timelines/index.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/cluster_settings.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts" + "plugin": "uptime", + "path": "x-pack/plugins/uptime/server/legacy_uptime/uptime_server.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/indices/delete_indices_route.ts" + "plugin": "watcher", + "path": "x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/routes/create_prebuilt_saved_objects.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/routes/delete_prebuilt_saved_objects.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/onboarding/routes/install_risk_scores.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/exceptions/api/manage_exceptions/route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/dashboards/routes/get_dashboards_by_tags.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_score_preview_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_init_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_enable_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_disable_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_score_calculation_route.ts" - }, - { - "plugin": "serverless", - "path": "x-pack/plugins/serverless/server/plugin.ts" - }, - { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts" - }, - { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/snapshots.ts" - }, - { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/restore.ts" - }, - { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/policy.ts" - }, - { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/policy.ts" - }, - { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/policy.ts" - }, - { - "plugin": "synthetics", - "path": "x-pack/plugins/synthetics/server/server.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/update_index_settings.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/cluster_settings.ts" - }, - { - "plugin": "uptime", - "path": "x-pack/plugins/uptime/server/legacy_uptime/uptime_server.ts" - }, - { - "plugin": "watcher", - "path": "x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts" - }, - { - "plugin": "watcher", - "path": "x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts" + "plugin": "watcher", + "path": "x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts" }, { "plugin": "watcher", @@ -7465,6 +7361,186 @@ "plugin": "@kbn/core-http-server-internal", "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/types.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/setup/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/setup/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/app/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/app/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/preconfiguration/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/preconfiguration/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/health_check/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/message_signing_service/index.ts" + }, { "plugin": "@kbn/core-http-router-server-mocks", "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts" @@ -7637,6 +7713,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" + }, { "plugin": "encryptedSavedObjects", "path": "x-pack/plugins/encrypted_saved_objects/server/routes/key_rotation.test.ts" @@ -7933,285 +8013,105 @@ "plugin": "spaces", "path": "x-pack/plugins/spaces/server/routes/api/external/copy_to_space.test.ts" }, - { - "plugin": "spaces", - "path": "x-pack/plugins/spaces/server/routes/api/external/disable_legacy_url_aliases.test.ts" - }, - { - "plugin": "spaces", - "path": "x-pack/plugins/spaces/server/routes/api/external/get_shareable_references.test.ts" - }, - { - "plugin": "spaces", - "path": "x-pack/plugins/spaces/server/routes/api/external/post.test.ts" - }, - { - "plugin": "spaces", - "path": "x-pack/plugins/spaces/server/routes/api/external/update_objects_spaces.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" - }, - { - "plugin": "home", - "path": "src/plugins/home/server/plugin.test.ts" - }, - { - "plugin": "home", - "path": "src/plugins/home/server/plugin.test.ts" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/routes/index.test.ts" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/routes/index.test.ts" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/routes/index.test.ts" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/routes/index.test.ts" - }, - { - "plugin": "@kbn/core-capabilities-server-internal", - "path": "packages/core/capabilities/core-capabilities-server-internal/src/capabilities_service.test.ts" - }, - { - "plugin": "@kbn/core-capabilities-server-internal", - "path": "packages/core/capabilities/core-capabilities-server-internal/src/capabilities_service.test.ts" - }, - { - "plugin": "@kbn/core-capabilities-server-internal", - "path": "packages/core/capabilities/core-capabilities-server-internal/src/capabilities_service.test.ts" - }, - { - "plugin": "@kbn/core-capabilities-server-internal", - "path": "packages/core/capabilities/core-capabilities-server-internal/src/capabilities_service.test.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/types.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/setup/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/setup/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + { + "plugin": "spaces", + "path": "x-pack/plugins/spaces/server/routes/api/external/disable_legacy_url_aliases.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "spaces", + "path": "x-pack/plugins/spaces/server/routes/api/external/get_shareable_references.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "spaces", + "path": "x-pack/plugins/spaces/server/routes/api/external/post.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "spaces", + "path": "x-pack/plugins/spaces/server/routes/api/external/update_objects_spaces.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + "plugin": "home", + "path": "src/plugins/home/server/plugin.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/app/index.ts" + "plugin": "home", + "path": "src/plugins/home/server/plugin.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/app/index.ts" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/routes/index.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/preconfiguration/index.ts" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/routes/index.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/preconfiguration/index.ts" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/routes/index.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/routes/index.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/health_check/index.ts" + "plugin": "@kbn/core-capabilities-server-internal", + "path": "packages/core/capabilities/core-capabilities-server-internal/src/capabilities_service.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" + "plugin": "@kbn/core-capabilities-server-internal", + "path": "packages/core/capabilities/core-capabilities-server-internal/src/capabilities_service.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" + "plugin": "@kbn/core-capabilities-server-internal", + "path": "packages/core/capabilities/core-capabilities-server-internal/src/capabilities_service.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/message_signing_service/index.ts" + "plugin": "@kbn/core-capabilities-server-internal", + "path": "packages/core/capabilities/core-capabilities-server-internal/src/capabilities_service.test.ts" }, { "plugin": "encryptedSavedObjects", @@ -8531,13 +8431,25 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/update_rule.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + }, { "plugin": "guidedOnboarding", "path": "src/plugins/guided_onboarding/server/routes/plugin_state_routes.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/indices/create_index_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/stored_scripts/create_script_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/tags/routes/create_tag.ts" }, { "plugin": "infra", @@ -8759,26 +8671,6 @@ "plugin": "licenseManagement", "path": "x-pack/plugins/license_management/server/routes/api/license/register_license_route.ts" }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/update_endpoint_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/update_exception_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_item/update_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list/update_list_route.ts" - }, { "plugin": "logstash", "path": "x-pack/plugins/logstash/server/routes/pipeline/save.ts" @@ -8795,18 +8687,6 @@ "plugin": "rollup", "path": "x-pack/plugins/rollup/server/routes/api/jobs/register_create_route.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/indices/create_index_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/stored_scripts/create_script_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/tags/routes/create_tag.ts" - }, { "plugin": "snapshotRestore", "path": "x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts" @@ -8883,6 +8763,58 @@ "plugin": "@kbn/core-http-server-internal", "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/types.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/settings/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" + }, { "plugin": "@kbn/core-http-router-server-mocks", "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts" @@ -8919,6 +8851,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" + }, { "plugin": "globalSearch", "path": "x-pack/plugins/global_search/server/routes/index.test.ts" @@ -8967,85 +8903,33 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/legacy/update.test.ts" }, - { - "plugin": "remoteClusters", - "path": "x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts" - }, - { - "plugin": "crossClusterReplication", - "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/auto_follow_pattern/register_update_route.test.ts" - }, - { - "plugin": "crossClusterReplication", - "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/follower_index/register_pause_route.test.ts" - }, - { - "plugin": "crossClusterReplication", - "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/follower_index/register_resume_route.test.ts" - }, - { - "plugin": "crossClusterReplication", - "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/follower_index/register_unfollow_route.test.ts" - }, - { - "plugin": "crossClusterReplication", - "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/follower_index/register_update_route.test.ts" - }, - { - "plugin": "spaces", - "path": "x-pack/plugins/spaces/server/routes/api/external/put.test.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/types.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + { + "plugin": "remoteClusters", + "path": "x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + "plugin": "crossClusterReplication", + "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/auto_follow_pattern/register_update_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + "plugin": "crossClusterReplication", + "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/follower_index/register_pause_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/settings/index.ts" + "plugin": "crossClusterReplication", + "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/follower_index/register_resume_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" + "plugin": "crossClusterReplication", + "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/follower_index/register_unfollow_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" + "plugin": "crossClusterReplication", + "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/follower_index/register_update_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" + "plugin": "spaces", + "path": "x-pack/plugins/spaces/server/routes/api/external/put.test.ts" }, { "plugin": "indexManagement", @@ -9273,30 +9157,6 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, - { - "plugin": "infra", - "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" - }, - { - "plugin": "enterpriseSearch", - "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/security.ts" - }, - { - "plugin": "enterpriseSearch", - "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts" - }, - { - "plugin": "enterpriseSearch", - "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_item/patch_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list/patch_list_route.ts" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/patch_timelines/index.ts" @@ -9313,6 +9173,22 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/pinned_events/persist_pinned_event.ts" }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, + { + "plugin": "enterpriseSearch", + "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/security.ts" + }, + { + "plugin": "enterpriseSearch", + "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts" + }, + { + "plugin": "enterpriseSearch", + "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts" + }, { "plugin": "@kbn/core-http-router-server-internal", "path": "packages/core/http/core-http-router-server-internal/src/router.ts" @@ -9325,6 +9201,14 @@ "plugin": "@kbn/core-http-server-internal", "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/types.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + }, { "plugin": "@kbn/core-http-router-server-mocks", "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts" @@ -9382,16 +9266,12 @@ "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, { - "plugin": "ruleRegistry", - "path": "x-pack/plugins/rule_registry/server/routes/__mocks__/server.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/types.ts" + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + "plugin": "ruleRegistry", + "path": "x-pack/plugins/rule_registry/server/routes/__mocks__/server.ts" }, { "plugin": "indexManagement", @@ -9643,10 +9523,6 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/maintenance_window/delete_maintenance_window.ts" }, - { - "plugin": "observability", - "path": "x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts" - }, { "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/server/routes/tags/delete_tag.ts" @@ -9655,6 +9531,30 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/delete_index_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/delete_timelines/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/notes/delete_note.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/stored_scripts/delete_script_route.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts" + }, { "plugin": "infra", "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" @@ -9815,30 +9715,6 @@ "plugin": "ingestPipelines", "path": "x-pack/plugins/ingest_pipelines/server/routes/api/delete.ts" }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/delete_endpoint_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/delete_exception_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/delete_exception_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_index/delete_list_index_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list_item/delete_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/list/delete_list_route.ts" - }, { "plugin": "logstash", "path": "x-pack/plugins/logstash/server/routes/pipeline/delete.ts" @@ -9847,26 +9723,6 @@ "plugin": "reporting", "path": "x-pack/plugins/reporting/server/test_helpers/create_mock_reportingplugin.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/delete_index_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/delete_timelines/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/notes/delete_note.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/stored_scripts/delete_script_route.ts" - }, { "plugin": "snapshotRestore", "path": "x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts" @@ -9919,6 +9775,54 @@ "plugin": "@kbn/core-http-server-internal", "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/types.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" + }, { "plugin": "@kbn/core-http-router-server-mocks", "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts" @@ -9951,6 +9855,10 @@ "plugin": "ecsDataQualityDashboard", "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" + }, { "plugin": "globalSearch", "path": "x-pack/plugins/global_search/server/routes/index.test.ts" @@ -10001,71 +9909,23 @@ }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/maintenance_window/delete_maintenance_window.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/maintenance_window/delete_maintenance_window.test.ts" - }, - { - "plugin": "remoteClusters", - "path": "x-pack/plugins/remote_clusters/server/routes/api/delete_route.test.ts" - }, - { - "plugin": "crossClusterReplication", - "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/auto_follow_pattern/register_delete_route.test.ts" - }, - { - "plugin": "spaces", - "path": "x-pack/plugins/spaces/server/routes/api/external/delete.test.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/types.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" + "path": "x-pack/plugins/alerting/server/routes/maintenance_window/delete_maintenance_window.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/output/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/maintenance_window/delete_maintenance_window.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" + "plugin": "remoteClusters", + "path": "x-pack/plugins/remote_clusters/server/routes/api/delete_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" + "plugin": "crossClusterReplication", + "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/auto_follow_pattern/register_delete_route.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" + "plugin": "spaces", + "path": "x-pack/plugins/spaces/server/routes/api/external/delete.test.ts" }, { "plugin": "indexManagement", @@ -13665,10 +13525,6 @@ "deprecated": false, "trackAdoption": true, "references": [ - { - "plugin": "@kbn/core-http-router-server-mocks", - "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" - }, { "plugin": "dataViews", "path": "src/plugins/data_views/server/rest_api_routes/public/runtime_fields/get_runtime_field.ts" @@ -13725,6 +13581,74 @@ "plugin": "data", "path": "src/plugins/data/server/scripts/route.ts" }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/find_endpoint_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/find_exception_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_item/find_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_index/find_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/internal/find_lists_by_size_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/read_endpoint_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/read_exception_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/read_exception_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_index/read_list_index_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_item/read_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list/read_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_privileges/read_list_privileges_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/summary_exception_list_route.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/routes/telemetry_config.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/routes/telemetry_config.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/routes/telemetry_last_reported.ts" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/json_schema.ts" @@ -13942,276 +13866,268 @@ "path": "x-pack/plugins/ml/server/routes/management.ts" }, { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_config.ts" - }, - { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_config.ts" - }, - { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_last_reported.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/live_query/get_live_query_details_route.ts" }, { - "plugin": "logsShared", - "path": "x-pack/plugins/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/live_query/get_live_query_results_route.ts" }, { - "plugin": "infra", - "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/live_query/find_live_query_route.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/custom_elements/find.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/custom_elements/get.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/shareables/download.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/status/create_status_route.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/workpad/find.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policies.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/workpad/get.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policy.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/workpad/resolve.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_status_for_agent_policy.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/templates/list.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_package_policies.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/functions/functions.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agents.ts" }, { - "plugin": "cloudDefend", - "path": "x-pack/plugins/cloud_defend/server/routes/policies/policies.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_details.ts" }, { - "plugin": "cloudDefend", - "path": "x-pack/plugins/cloud_defend/server/routes/status/status.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/pack/find_pack_route.ts" }, { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/pack/read_pack_route.ts" }, { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/privileges_check/privileges_check_route.ts" }, { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/server/routes/status/status.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/asset/get_assets_status_route.ts" }, { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/server/routes/csp_rule_template/get_csp_rule_template.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts" }, { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/server/routes/detection_engine/get_detection_engine_alerts_count_by_rule_tags.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts" }, { - "plugin": "fileUpload", - "path": "x-pack/plugins/file_upload/server/routes.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_cluster_health/get_cluster_health_route.ts" }, { - "plugin": "kubernetesSecurity", - "path": "x-pack/plugins/kubernetes_security/server/routes/aggregate.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_space_health/get_space_health_route.ts" }, { - "plugin": "kubernetesSecurity", - "path": "x-pack/plugins/kubernetes_security/server/routes/count.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.ts" }, { - "plugin": "kubernetesSecurity", - "path": "x-pack/plugins/kubernetes_security/server/routes/multi_terms_aggregate.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/server/mvt/mvt_routes.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/server/mvt/mvt_routes.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/server/data_indexing/indexing_routes.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/server/data_indexing/indexing_routes.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/tags/read_tags/route.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/server/routes.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/server/routes.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/live_query/get_live_query_details_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/live_query/get_live_query_results_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/live_query/find_live_query_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/status/create_status_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/details.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policies.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policy.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/state.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_status_for_agent_policy.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/audit_log.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_package_policies.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/list.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agents.ts" + "plugin": "@kbn/core-http-router-server-mocks", + "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_details.ts" + { + "plugin": "logsShared", + "path": "x-pack/plugins/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/pack/find_pack_route.ts" + "plugin": "infra", + "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/pack/read_pack_route.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/custom_elements/find.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/privileges_check/privileges_check_route.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/custom_elements/get.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/asset/get_assets_status_route.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/shareables/download.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_cluster_health/get_cluster_health_route.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/workpad/find.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_space_health/get_space_health_route.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/workpad/get.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_events/get_rule_execution_events_route.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/workpad/resolve.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/templates/list.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/functions/functions.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_status/get_prebuilt_rules_status_route.ts" + "plugin": "cloudDefend", + "path": "x-pack/plugins/cloud_defend/server/routes/policies/policies.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts" + "plugin": "cloudDefend", + "path": "x-pack/plugins/cloud_defend/server/routes/status/status.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts" + "plugin": "cloudSecurityPosture", + "path": "x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts" + "plugin": "cloudSecurityPosture", + "path": "x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/tags/read_tags/route.ts" + "plugin": "cloudSecurityPosture", + "path": "x-pack/plugins/cloud_security_posture/server/routes/status/status.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" + "plugin": "cloudSecurityPosture", + "path": "x-pack/plugins/cloud_security_posture/server/routes/csp_rule_template/get_csp_rule_template.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" + "plugin": "cloudSecurityPosture", + "path": "x-pack/plugins/cloud_security_posture/server/routes/detection_engine/get_detection_engine_alerts_count_by_rule_tags.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" + "plugin": "fileUpload", + "path": "x-pack/plugins/file_upload/server/routes.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts" + "plugin": "kubernetesSecurity", + "path": "x-pack/plugins/kubernetes_security/server/routes/aggregate.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts" + "plugin": "kubernetesSecurity", + "path": "x-pack/plugins/kubernetes_security/server/routes/count.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.ts" + "plugin": "kubernetesSecurity", + "path": "x-pack/plugins/kubernetes_security/server/routes/multi_terms_aggregate.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/server/mvt/mvt_routes.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/details.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/server/mvt/mvt_routes.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/server/data_indexing/indexing_routes.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/state.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/server/data_indexing/indexing_routes.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/audit_log.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/server/routes.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/list.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/server/routes.ts" }, { "plugin": "sessionView", @@ -14233,10 +14149,6 @@ "plugin": "sessionView", "path": "x-pack/plugins/session_view/server/routes/get_total_io_bytes_route.ts" }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/server/routes/api/privileges.ts" - }, { "plugin": "transform", "path": "x-pack/plugins/transform/server/routes/api/transforms_audit_messages.ts" @@ -14458,8 +14370,8 @@ "trackAdoption": true, "references": [ { - "plugin": "@kbn/core-http-router-server-mocks", - "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" + "plugin": "@kbn/core-apps-server-internal", + "path": "packages/core/apps/core-apps-server-internal/src/core_app.ts" }, { "plugin": "dataViews", @@ -14485,6 +14397,38 @@ "plugin": "data", "path": "src/plugins/data/server/query/routes.ts" }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/update_endpoint_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/update_exception_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_item/update_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list/update_list_route.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/routes/telemetry_last_reported.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/annotations.ts" @@ -14526,12 +14470,24 @@ "path": "x-pack/plugins/ml/server/routes/anomaly_detectors.ts" }, { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts" }, { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_last_reported.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/pack/update_pack_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts" + }, + { + "plugin": "@kbn/core-http-router-server-mocks", + "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" }, { "plugin": "logsShared", @@ -14557,26 +14513,6 @@ "plugin": "canvas", "path": "x-pack/plugins/canvas/server/routes/workpad/update.ts" }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/pack/update_pack_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/update_rule/route.ts" - }, { "plugin": "transform", "path": "x-pack/plugins/transform/server/routes/api/transforms.ts" @@ -14596,6 +14532,14 @@ { "plugin": "canvas", "path": "x-pack/plugins/canvas/server/routes/workpad/update.test.ts" + }, + { + "plugin": "@kbn/core-apps-server-internal", + "path": "packages/core/apps/core-apps-server-internal/src/core_app.test.ts" + }, + { + "plugin": "@kbn/core-apps-server-internal", + "path": "packages/core/apps/core-apps-server-internal/src/core_app.test.ts" } ], "returnComment": [], @@ -14665,10 +14609,6 @@ "deprecated": false, "trackAdoption": true, "references": [ - { - "plugin": "@kbn/core-http-router-server-mocks", - "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" - }, { "plugin": "dataViews", "path": "src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts" @@ -14730,36 +14670,96 @@ "path": "src/plugins/data/server/search/routes/session.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/search/routes/search.ts" + "plugin": "data", + "path": "src/plugins/data/server/search/routes/search.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/server/query/routes.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/server/query/routes.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/server/query/routes.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/server/kql_telemetry/route.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/server/autocomplete/value_suggestions_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/create_endpoint_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/create_endpoint_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/create_exception_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/create_exception_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_index/create_list_index_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_item/create_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list/create_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/duplicate_exception_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/export_exception_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_index/export_list_item_route.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/query/routes.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/internal/create_exception_filter_route.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/query/routes.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/import_exceptions_route.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/query/routes.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list/import_list_item_route.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/kql_telemetry/route.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/internal/create_exceptions_list_route.ts" }, { - "plugin": "unifiedSearch", - "path": "src/plugins/unified_search/server/autocomplete/value_suggestions_route.ts" + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/server/routes/log_rate_analysis.ts" + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/routes/telemetry_opt_in.ts" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/server/routes/log_categorization.ts" + "plugin": "telemetry", + "path": "src/plugins/telemetry/server/routes/telemetry_usage_stats.ts" }, { "plugin": "ml", @@ -15053,66 +15053,6 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/alerting.ts" }, - { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts" - }, - { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_opt_in.ts" - }, - { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_usage_stats.ts" - }, - { - "plugin": "logsShared", - "path": "x-pack/plugins/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" - }, - { - "plugin": "infra", - "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" - }, - { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/custom_elements/create.ts" - }, - { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/shareables/zip.ts" - }, - { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/workpad/create.ts" - }, - { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/workpad/import.ts" - }, - { - "plugin": "fileUpload", - "path": "x-pack/plugins/file_upload/server/routes.ts" - }, - { - "plugin": "fileUpload", - "path": "x-pack/plugins/file_upload/server/routes.ts" - }, - { - "plugin": "fileUpload", - "path": "x-pack/plugins/file_upload/server/routes.ts" - }, - { - "plugin": "fileUpload", - "path": "x-pack/plugins/file_upload/server/routes.ts" - }, - { - "plugin": "maps", - "path": "x-pack/plugins/maps/server/data_indexing/indexing_routes.ts" - }, - { - "plugin": "maps", - "path": "x-pack/plugins/maps/server/data_indexing/indexing_routes.ts" - }, { "plugin": "osquery", "path": "x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts" @@ -15131,35 +15071,35 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_cluster_health/get_cluster_health_route.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_rule_health/get_rule_health_route.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_space_health/get_space_health_route.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/setup/setup_health_route.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_cluster_health/get_cluster_health_route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_rule_health/get_rule_health_route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/get_space_health/get_space_health_route.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts" + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/setup/setup_health_route.ts" }, { "plugin": "securitySolution", @@ -15233,6 +15173,66 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/routes/suggestions/index.ts" }, + { + "plugin": "@kbn/core-http-router-server-mocks", + "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/server/routes/log_rate_analysis.ts" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/server/routes/log_categorization.ts" + }, + { + "plugin": "logsShared", + "path": "x-pack/plugins/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, + { + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/custom_elements/create.ts" + }, + { + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/shareables/zip.ts" + }, + { + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/workpad/create.ts" + }, + { + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/workpad/import.ts" + }, + { + "plugin": "fileUpload", + "path": "x-pack/plugins/file_upload/server/routes.ts" + }, + { + "plugin": "fileUpload", + "path": "x-pack/plugins/file_upload/server/routes.ts" + }, + { + "plugin": "fileUpload", + "path": "x-pack/plugins/file_upload/server/routes.ts" + }, + { + "plugin": "fileUpload", + "path": "x-pack/plugins/file_upload/server/routes.ts" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/server/data_indexing/indexing_routes.ts" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/server/data_indexing/indexing_routes.ts" + }, { "plugin": "transform", "path": "x-pack/plugins/transform/server/routes/api/field_histograms.ts" @@ -15394,16 +15394,12 @@ "trackAdoption": true, "references": [ { - "plugin": "@kbn/core-http-router-server-mocks", - "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" - }, - { - "plugin": "logsShared", - "path": "x-pack/plugins/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_item/patch_list_item_route.ts" }, { - "plugin": "infra", - "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list/patch_list_route.ts" }, { "plugin": "securitySolution", @@ -15413,6 +15409,18 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts" }, + { + "plugin": "@kbn/core-http-router-server-mocks", + "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" + }, + { + "plugin": "logsShared", + "path": "x-pack/plugins/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "@kbn/core-http-router-server-internal", "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.ts" @@ -15485,10 +15493,6 @@ "deprecated": false, "trackAdoption": true, "references": [ - { - "plugin": "@kbn/core-http-router-server-mocks", - "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" - }, { "plugin": "dataViews", "path": "src/plugins/data_views/server/rest_api_routes/public/runtime_fields/delete_runtime_field.ts" @@ -15517,6 +15521,30 @@ "plugin": "data", "path": "src/plugins/data/server/query/routes.ts" }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/delete_endpoint_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/delete_exception_list_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/delete_exception_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_index/delete_list_index_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_item/delete_list_item_route.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list/delete_list_route.ts" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/annotations.ts" @@ -15549,6 +15577,26 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/anomaly_detectors.ts" }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/saved_query/delete_saved_query_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/pack/delete_pack_route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts" + }, + { + "plugin": "@kbn/core-http-router-server-mocks", + "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" + }, { "plugin": "logsShared", "path": "x-pack/plugins/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" @@ -15569,22 +15617,6 @@ "plugin": "maps", "path": "x-pack/plugins/maps/server/data_indexing/indexing_routes.ts" }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/saved_query/delete_saved_query_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/pack/delete_pack_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/delete_rule/route.ts" - }, { "plugin": "@kbn/core-http-router-server-internal", "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 19313e1315117..16a6084dad9d5 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-08-25 +date: 2023-09-04 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 f983f4354d701..1c09e6a0b36d4 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-08-25 +date: 2023-09-04 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 51b40daaad4a6..1a24f8471163c 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-08-25 +date: 2023-09-04 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 c18651d90d895..47643405acc3e 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-08-25 +date: 2023-09-04 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 924b903c56012..0361011ea4464 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-08-25 +date: 2023-09-04 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 b1e64c3cff3fa..6ba2126453c6c 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-08-25 +date: 2023-09-04 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 d0c9c77a6d392..a26bcba8cf69b 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-08-25 +date: 2023-09-04 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 43eed17f4df67..c0738dcf46aaa 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-08-25 +date: 2023-09-04 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 69fa705ce9eb6..3dfe8c59eb2e8 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-08-25 +date: 2023-09-04 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 34392cadbd926..a5d596027199b 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-08-25 +date: 2023-09-04 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 954db7f7b83d5..b7097f4f42d61 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-08-25 +date: 2023-09-04 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 851eadda6f6dd..96ca9047cc56e 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-08-25 +date: 2023-09-04 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 a933da8139d74..2f4b73d3fa360 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-08-25 +date: 2023-09-04 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 d1f7848afb1c6..18918e753aaa7 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-08-25 +date: 2023-09-04 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 ea0bb64ff9b9a..f4a53b0cf8625 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-08-25 +date: 2023-09-04 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 059ec4a356f89..aff7c06b61b86 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-08-25 +date: 2023-09-04 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 f08cdca794424..c0c53ad35ebf5 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-08-25 +date: 2023-09-04 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 b721f86ad4573..126605bc64a11 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-08-25 +date: 2023-09-04 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 f36e1581c9a1a..b70d32d8873e2 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-08-25 +date: 2023-09-04 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 51a3a2cc00f29..45427a87ca146 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-08-25 +date: 2023-09-04 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 b6e5264aa29eb..e0889d91e8655 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-08-25 +date: 2023-09-04 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 52b07564db38e..e050b16b796d2 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-08-25 +date: 2023-09-04 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 f91f7398af2bc..9f89f3f7e0c72 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-08-25 +date: 2023-09-04 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 f8a4a909f117d..9159c7ef68551 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-08-25 +date: 2023-09-04 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 57ca26e886de4..25a2db252da61 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-08-25 +date: 2023-09-04 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 602df668a1de6..5935efa5d5cae 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-08-25 +date: 2023-09-04 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 30b86128e56af..a1b380a57004a 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-08-25 +date: 2023-09-04 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 aef7b965b4ca7..742b72e989415 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-08-25 +date: 2023-09-04 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 a05edab3226d7..bcd8350316386 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-08-25 +date: 2023-09-04 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 fbd16974d6708..712ac608b2a73 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-08-25 +date: 2023-09-04 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 fc39359d73e46..4b11f107b8106 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-08-25 +date: 2023-09-04 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 282ba71bba81e..587fd854f47e2 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-08-25 +date: 2023-09-04 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 c5cb58b779285..60f337b9360c6 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-08-25 +date: 2023-09-04 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 76bac9da59c41..4132d3df13f31 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-08-25 +date: 2023-09-04 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 52cbe712f1a01..ae0babce5eb43 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-08-25 +date: 2023-09-04 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 319a5cfdc9321..66ddff8834c28 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_core_plugins_browser_mocks.devdocs.json index 5671c40bc1f8c..38a7c61a027ac 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.devdocs.json +++ b/api_docs/kbn_core_plugins_browser_mocks.devdocs.json @@ -92,7 +92,9 @@ "label": "createPluginInitializerContext", "description": [], "signature": [ - "(config?: unknown) => ", + "(config?: unknown, { buildFlavor }?: { buildFlavor?: ", + "BuildFlavor", + " | undefined; }) => ", { "pluginId": "@kbn/core-plugins-browser", "scope": "common", @@ -120,6 +122,22 @@ "path": "packages/core/plugins/core-plugins-browser-mocks/src/plugins_service.mock.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-plugins-browser-mocks", + "id": "def-common.pluginsServiceMock.createPluginInitializerContext.$2", + "type": "Object", + "tags": [], + "label": "__1", + "description": [], + "signature": [ + "{ buildFlavor?: ", + "BuildFlavor", + " | undefined; }" + ], + "path": "packages/core/plugins/core-plugins-browser-mocks/src/plugins_service.mock.ts", + "deprecated": false, + "trackAdoption": false } ] } diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 9c3db5ef26673..7d25a2ccb88c1 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 6 | 0 | 6 | 0 | +| 7 | 0 | 7 | 0 | ## Common diff --git a/api_docs/kbn_core_plugins_server.devdocs.json b/api_docs/kbn_core_plugins_server.devdocs.json index 98b1596549758..1d895c5714572 100644 --- a/api_docs/kbn_core_plugins_server.devdocs.json +++ b/api_docs/kbn_core_plugins_server.devdocs.json @@ -436,6 +436,29 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/core-plugins-server", + "id": "def-common.PluginConfigDescriptor.dynamicConfig", + "type": "Object", + "tags": [], + "label": "dynamicConfig", + "description": [ + "\nList of configuration properties that can be dynamically changed via the PUT /_settings API." + ], + "signature": [ + { + "pluginId": "@kbn/core-plugins-server", + "scope": "common", + "docId": "kibKbnCorePluginsServerPluginApi", + "section": "def-common.DynamicConfigDescriptor", + "text": "DynamicConfigDescriptor" + }, + " | undefined" + ], + "path": "packages/core/plugins/core-plugins-server/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/core-plugins-server", "id": "def-common.PluginConfigDescriptor.schema", @@ -1050,6 +1073,31 @@ ], "enums": [], "misc": [ + { + "parentPluginId": "@kbn/core-plugins-server", + "id": "def-common.DynamicConfigDescriptor", + "type": "Type", + "tags": [], + "label": "DynamicConfigDescriptor", + "description": [ + "\nType defining the list of configuration properties that can be dynamically updated\nObject properties can either be fully exposed or narrowed down to specific keys.\n" + ], + "signature": [ + "{ [Key in keyof T]?: (T[Key] extends Maybe ? boolean : T[Key] extends Maybe ? boolean | ", + { + "pluginId": "@kbn/core-plugins-server", + "scope": "common", + "docId": "kibKbnCorePluginsServerPluginApi", + "section": "def-common.DynamicConfigDescriptor", + "text": "DynamicConfigDescriptor" + }, + " : boolean) | undefined; }" + ], + "path": "packages/core/plugins/core-plugins-server/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-plugins-server", "id": "def-common.ExposedToBrowserDescriptor", @@ -1057,7 +1105,7 @@ "tags": [], "label": "ExposedToBrowserDescriptor", "description": [ - "\nType defining the list of configuration properties that will be exposed on the client-side\nObject properties can either be fully exposed\n" + "\nType defining the list of configuration properties that will be exposed on the client-side\nObject properties can either be fully exposed or narrowed down to specific keys.\n" ], "signature": [ "{ [Key in keyof T]?: (T[Key] extends Maybe ? boolean : T[Key] extends Maybe ? boolean | ", diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index fd399fbcb4cf6..7b8fd5a52e50a 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 58 | 0 | 26 | 0 | +| 60 | 0 | 26 | 0 | ## Common diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 23e9e17d835fd..7f7d3e21cdeb2 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-08-25 +date: 2023-09-04 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 07193e3ee38ba..ad366371f39dd 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-08-25 +date: 2023-09-04 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 e3c73bd229375..a4971c4a44666 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-08-25 +date: 2023-09-04 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 b06a09356fdaf..d319f617aba6c 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-08-25 +date: 2023-09-04 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 7b5930c9c0d32..2924d830ad0b3 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-08-25 +date: 2023-09-04 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 2313c40626dba..7972293e52f74 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-08-25 +date: 2023-09-04 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 82fe97e426a21..d1a6940e31b21 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json index 5072b3241b2ab..94d374afbba24 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json @@ -1382,14 +1382,14 @@ "plugin": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/helpers/build_saved_object.ts" }, - { - "plugin": "@kbn/core-saved-objects-browser-mocks", - "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/saved_objects_service.mock.ts" - }, { "plugin": "visualizations", "path": "src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx" }, + { + "plugin": "@kbn/core-saved-objects-browser-mocks", + "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/saved_objects_service.mock.ts" + }, { "plugin": "@kbn/core-saved-objects-browser-internal", "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.ts" @@ -3004,12 +3004,12 @@ "path": "src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/application/utils/search_utils.ts" + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/common/types/index.ts" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/application/utils/search_utils.ts" + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/common/types/index.ts" }, { "plugin": "ml", @@ -3020,12 +3020,12 @@ "path": "x-pack/plugins/ml/common/types/kibana.ts" }, { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/common/types/index.ts" + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/application/utils/search_utils.ts" }, { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/common/types/index.ts" + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/application/utils/search_utils.ts" }, { "plugin": "dashboardEnhanced", diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 12a4ad38a960a..4706ebf127165 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_core_saved_objects_api_server.devdocs.json index 0cf2458cc39be..89f29c9e91e81 100644 --- a/api_docs/kbn_core_saved_objects_api_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_server.devdocs.json @@ -2358,10 +2358,6 @@ "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" }, - { - "plugin": "@kbn/core-saved-objects-browser-mocks", - "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" - }, { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" @@ -2374,22 +2370,6 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/logs.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/flights.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, { "plugin": "osquery", "path": "x-pack/plugins/osquery/server/routes/pack/read_pack_route.ts" @@ -2478,6 +2458,26 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-browser-mocks", + "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/logs.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/flights.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" + }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/rules_client/lib/siem_legacy_actions/retrieve_migrated_legacy_actions.mock.ts" @@ -2794,6 +2794,22 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/types.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts" + }, { "plugin": "savedSearch", "path": "src/plugins/saved_search/server/saved_objects/search_migrations.ts" @@ -2830,22 +2846,6 @@ "plugin": "enterpriseSearch", "path": "x-pack/plugins/enterprise_search/server/collectors/lib/telemetry.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts" - }, { "plugin": "taskManager", "path": "x-pack/plugins/task_manager/server/task_store.test.ts" @@ -7942,7 +7942,7 @@ "tags": [], "label": "version", "description": [ - "\nAn opaque version number which changes on each successful write operation.\nCan be used for implementing optimistic concurrency control." + "\nAn opaque version number which changes on each successful write operation.\nCan be used for implementing optimistic concurrency control.\nUnused for multi-namespace objects" ], "signature": [ "string | undefined" @@ -8028,6 +8028,22 @@ "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/update.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-common.SavedObjectsUpdateOptions.migrationVersionCompatibility", + "type": "CompoundType", + "tags": [], + "label": "migrationVersionCompatibility", + "description": [ + "{@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility}" + ], + "signature": [ + "\"raw\" | \"compatible\" | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/update.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 73e972f3333f1..99365f9ea9b68 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 351 | 1 | 5 | 1 | +| 352 | 1 | 5 | 1 | ## Common 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 642401a5bacff..d8f8413add7b5 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-08-25 +date: 2023-09-04 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 cd058fbb2adc0..1f68cdbe8d3ac 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-08-25 +date: 2023-09-04 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 64cb7e7f85910..c9e4bef10f00d 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-08-25 +date: 2023-09-04 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 2b3e5bbc6538f..91ffd645724d8 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-08-25 +date: 2023-09-04 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 a264ce892fdb4..e5b662da7c3be 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-08-25 +date: 2023-09-04 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 5519f4431b77e..7a0ceb77a896a 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.devdocs.json b/api_docs/kbn_core_saved_objects_common.devdocs.json index c1b6b92e592fb..34f58a56a00b1 100644 --- a/api_docs/kbn_core_saved_objects_common.devdocs.json +++ b/api_docs/kbn_core_saved_objects_common.devdocs.json @@ -1077,6 +1077,22 @@ "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts" + }, { "plugin": "lists", "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" @@ -1109,22 +1125,6 @@ "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/host_risk_score_dashboards.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts" - }, { "plugin": "upgradeAssistant", "path": "x-pack/plugins/upgrade_assistant/common/types.ts" @@ -1930,6 +1930,30 @@ "plugin": "embeddable", "path": "src/plugins/embeddable/common/lib/inject.ts" }, + { + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" + }, + { + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" + }, + { + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" + }, + { + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" + }, + { + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" + }, + { + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" + }, { "plugin": "controls", "path": "src/plugins/controls/common/options_list/options_list_persistable_state.ts" @@ -1978,30 +2002,6 @@ "plugin": "controls", "path": "src/plugins/controls/common/control_group/control_group_persistable_state.ts" }, - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" - }, - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" - }, - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" - }, - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" - }, - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" - }, - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" - }, { "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index c049da542597a..1c22a053af476 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-08-25 +date: 2023-09-04 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 ded98b70d17b2..f43b058992acc 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-08-25 +date: 2023-09-04 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 f74c34896e225..f7bcc28c2c9be 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json index cbd8b5774457d..4788fa89a6be4 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json @@ -330,7 +330,7 @@ "id": "def-common.KibanaMigrator.Unnamed.$1", "type": "Object", "tags": [], - "label": "{\n client,\n typeRegistry,\n kibanaIndex,\n defaultIndexTypesMap,\n soMigrationsConfig,\n kibanaVersion,\n logger,\n docLinks,\n waitForMigrationCompletion,\n nodeRoles,\n }", + "label": "{\n client,\n typeRegistry,\n kibanaIndex,\n defaultIndexTypesMap,\n soMigrationsConfig,\n kibanaVersion,\n logger,\n docLinks,\n waitForMigrationCompletion,\n nodeRoles,\n esCapabilities,\n }", "description": [], "signature": [ { @@ -831,7 +831,7 @@ "\nMakes a clone of the source index into the target.\n" ], "signature": [ - "({ client, source, target, timeout, }: ", + "({ client, esCapabilities, source, target, timeout, }: ", "CloneIndexParams", ") => ", "TaskEither", @@ -856,7 +856,7 @@ "id": "def-common.cloneIndex.$1", "type": "Object", "tags": [], - "label": "{\n client,\n source,\n target,\n timeout = DEFAULT_TIMEOUT,\n}", + "label": "{\n client,\n esCapabilities,\n source,\n target,\n timeout = DEFAULT_TIMEOUT,\n}", "description": [], "signature": [ "CloneIndexParams" @@ -1020,7 +1020,7 @@ "\nCreates an index with the given mappings\n" ], "signature": [ - "({ client, indexName, mappings, aliases, timeout, }: ", + "({ client, indexName, mappings, esCapabilities, aliases, timeout, }: ", "CreateIndexParams", ") => ", "TaskEither", @@ -1043,7 +1043,7 @@ "id": "def-common.createIndex.$1", "type": "Object", "tags": [], - "label": "{\n client,\n indexName,\n mappings,\n aliases = [],\n timeout = DEFAULT_TIMEOUT,\n}", + "label": "{\n client,\n indexName,\n mappings,\n esCapabilities,\n aliases = [],\n timeout = DEFAULT_TIMEOUT,\n}", "description": [], "signature": [ "CreateIndexParams" @@ -3648,6 +3648,26 @@ "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", + "id": "def-common.KibanaMigratorOptions.esCapabilities", + "type": "Object", + "tags": [], + "label": "esCapabilities", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.ElasticsearchCapabilities", + "text": "ElasticsearchCapabilities" + } + ], + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false 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 c027da4479861..d16812104f5e9 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 124 | 0 | 90 | 46 | +| 125 | 0 | 91 | 46 | ## Common 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 a91570223cd66..f7d106af803f8 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_core_saved_objects_server.devdocs.json index 01acf47ab87de..1853a66e3f1b5 100644 --- a/api_docs/kbn_core_saved_objects_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_server.devdocs.json @@ -5823,10 +5823,6 @@ "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" }, - { - "plugin": "@kbn/core-saved-objects-browser-mocks", - "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" - }, { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" @@ -5839,22 +5835,6 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/logs.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" - }, - { - "plugin": "graph", - "path": "x-pack/plugins/graph/server/sample_data/flights.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, { "plugin": "osquery", "path": "x-pack/plugins/osquery/server/routes/pack/read_pack_route.ts" @@ -5943,6 +5923,26 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/saved_object/user_risk_score_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-browser-mocks", + "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/logs.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/ecommerce.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/server/sample_data/flights.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" + }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/rules_client/lib/siem_legacy_actions/retrieve_migrated_legacy_actions.mock.ts" @@ -6259,6 +6259,22 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/types.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts" + }, { "plugin": "savedSearch", "path": "src/plugins/saved_search/server/saved_objects/search_migrations.ts" @@ -6295,22 +6311,6 @@ "plugin": "enterpriseSearch", "path": "x-pack/plugins/enterprise_search/server/collectors/lib/telemetry.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_types.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_migrations.ts" - }, { "plugin": "taskManager", "path": "x-pack/plugins/task_manager/server/task_store.test.ts" @@ -8647,7 +8647,9 @@ "type": "Interface", "tags": [], "label": "SavedObjectsRawDocSource", - "description": [], + "description": [ + "\nSaved object document as stored in `_source` of doc in ES index\nSimilar to SavedObjectDoc and excludes `version`, includes `references`, has `attributes` in [typeMapping]\n" + ], "path": "packages/core/saved-objects/core-saved-objects-server/src/serialization.ts", "deprecated": false, "trackAdoption": false, @@ -9619,52 +9621,6 @@ "trackAdoption": false, "children": [], "returnComment": [] - }, - { - "parentPluginId": "@kbn/core-saved-objects-server", - "id": "def-common.SavedObjectsServiceSetup.getAllIndices", - "type": "Function", - "tags": [ - "deprecated" - ], - "label": "getAllIndices", - "description": [ - "\nReturns all (aliases to) kibana system indices used for saved object storage.\n" - ], - "signature": [ - "() => string[]" - ], - "path": "packages/core/saved-objects/core-saved-objects-server/src/contracts.ts", - "deprecated": true, - "trackAdoption": false, - "references": [ - { - "plugin": "@kbn/core-saved-objects-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts" - }, - { - "plugin": "@kbn/core-plugins-server-internal", - "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" - }, - { - "plugin": "@kbn/core-plugins-server-internal", - "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/server/plugin.ts" - }, - { - "plugin": "@kbn/core-saved-objects-server-mocks", - "path": "packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts" - }, - { - "plugin": "@kbn/core-saved-objects-server-mocks", - "path": "packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts" - } - ], - "children": [], - "returnComment": [] } ], "initialIsOpen": false @@ -10225,7 +10181,7 @@ "tags": [], "label": "getAllIndices", "description": [ - "\nReturns all (aliases to) kibana system indices used for saved object storage." + "\nReturns all (aliases to) kibana system indices used for saved object storage.\n" ], "signature": [ "() => string[]" @@ -10555,6 +10511,26 @@ "plugin": "lens", "path": "x-pack/plugins/lens/server/saved_objects.ts" }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/saved_objects/exception_list.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/server/saved_objects/tag.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings/timelines.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings/notes.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings/pinned_events.ts" + }, { "plugin": "cases", "path": "x-pack/plugins/cases/server/saved_object_types/cases.ts" @@ -10576,8 +10552,8 @@ "path": "x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/server/saved_objects/tag.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_saved_object_mappings.ts" }, { "plugin": "visualizations", @@ -10599,30 +10575,10 @@ "plugin": "graph", "path": "x-pack/plugins/graph/server/saved_objects/graph_workspace.ts" }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/saved_objects/exception_list.ts" - }, { "plugin": "maps", "path": "x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings/timelines.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings/notes.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/saved_object_mappings/pinned_events.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_saved_object_mappings.ts" - }, { "plugin": "dashboard", "path": "src/plugins/dashboard/server/dashboard_saved_object/dashboard_saved_object.ts" diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index b4991312049dc..4eba90ab01edf 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 548 | 1 | 122 | 4 | +| 547 | 1 | 121 | 4 | ## Common diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index c18e4f6b186f5..d9e15fcfaa14b 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-08-25 +date: 2023-09-04 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 ab3ed804b8929..ac3b0f16b3b63 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-08-25 +date: 2023-09-04 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 3ffc2a10dcb50..1a0222aaea429 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-08-25 +date: 2023-09-04 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 fae85b77a87f8..39440c3a31de9 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-08-25 +date: 2023-09-04 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 0653750d652e0..9875560220078 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-08-25 +date: 2023-09-04 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 50131b8af0e54..77d4ab765d093 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-08-25 +date: 2023-09-04 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 c1f9f255da1af..f3834ac7a3e9c 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-08-25 +date: 2023-09-04 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 1b4bc7ad3195e..3b179236a1fec 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-08-25 +date: 2023-09-04 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 cb10b4802f436..a74eeb190befd 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-08-25 +date: 2023-09-04 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 b15b426d64728..478f60ee9b5c8 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_core_test_helpers_kbn_server.devdocs.json index f410d08aa0a63..6631202ad7012 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.devdocs.json +++ b/api_docs/kbn_core_test_helpers_kbn_server.devdocs.json @@ -765,7 +765,17 @@ "label": "TestServerlessESUtils", "description": [], "signature": [ - "{ stop: () => Promise; es: any; }" + "Pick<", + { + "pluginId": "@kbn/core-test-helpers-kbn-server", + "scope": "common", + "docId": "kibKbnCoreTestHelpersKbnServerPluginApi", + "section": "def-common.TestElasticsearchUtils", + "text": "TestElasticsearchUtils" + }, + ", \"stop\" | \"es\"> & { getClient: () => ", + "default", + "; }" ], "path": "packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts", "deprecated": false, diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index f6085b691cc16..4798ed7c4e8df 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index a7adf454e1f5a..28327d1450d27 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-08-25 +date: 2023-09-04 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 0ae6f7975aec4..a0a137cd66142 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-08-25 +date: 2023-09-04 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 05c6b1bd9cb17..e72dc51ae7c33 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-08-25 +date: 2023-09-04 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 fbb44cd578b1a..da78f3ef086d5 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-08-25 +date: 2023-09-04 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 a64f94fa8437f..24dccb85bd7bf 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-08-25 +date: 2023-09-04 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 6bf7f4eba4c28..a8df8af702bf8 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-08-25 +date: 2023-09-04 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 bc1836935c6af..eda475abb8f02 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-08-25 +date: 2023-09-04 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 1b423390cc941..33665b6556280 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-08-25 +date: 2023-09-04 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 ab41775606b87..67c1e401ebc03 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-08-25 +date: 2023-09-04 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 a5fc533191ced..82bff56885e4f 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-08-25 +date: 2023-09-04 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 2cc03af761aa8..e767e704bd28a 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_core_usage_data_server.devdocs.json index 11fa425905aff..b2bd17618b373 100644 --- a/api_docs/kbn_core_usage_data_server.devdocs.json +++ b/api_docs/kbn_core_usage_data_server.devdocs.json @@ -1654,6 +1654,34 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/core-usage-data-server", + "id": "def-common.CoreUsageStats.apiCalls.savedObjectsImport.compatibilityModeEnabled.yes", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsImport.compatibilityModeEnabled.yes'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-usage-data-server", + "id": "def-common.CoreUsageStats.apiCalls.savedObjectsImport.compatibilityModeEnabled.no", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsImport.compatibilityModeEnabled.no'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/core-usage-data-server", "id": "def-common.CoreUsageStats.apiCalls.savedObjectsImport.overwriteEnabled.yes", diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 2f4089df0bcae..b158c355a8c55 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 153 | 0 | 142 | 0 | +| 155 | 0 | 144 | 0 | ## Common diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 8bfd936f84766..001146b5c0d0f 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-08-25 +date: 2023-09-04 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 79019ff7e9307..44e2e4dcf6f66 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-08-25 +date: 2023-09-04 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 33b0320b2151f..5c87cea7b6764 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-08-25 +date: 2023-09-04 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 dac2d7479eade..da791e96f6a8c 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-08-25 +date: 2023-09-04 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 b3e362e3243ca..f5ceb3c310b68 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-08-25 +date: 2023-09-04 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 9435ee18fa2e2..2788209ab090a 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-08-25 +date: 2023-09-04 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 45b3fba92f71d..14fdf1d5e5780 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index a5d2a718b2faf..1c0417b830e26 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-08-25 +date: 2023-09-04 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 9c6e4517bae59..0f89b6ba60ef0 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-08-25 +date: 2023-09-04 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 aa5c9a5d529df..f00fe4d608bc1 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-08-25 +date: 2023-09-04 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 3ce81a47fc7a4..7caeb321ed8d9 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-08-25 +date: 2023-09-04 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 14342591b6950..6edde9b4eab23 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-08-25 +date: 2023-09-04 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 7788ee617b2f3..ee19bda421aa0 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-08-25 +date: 2023-09-04 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 09416549c2a71..6c4a225090d01 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.devdocs.json b/api_docs/kbn_deeplinks_observability.devdocs.json index dbcbc0da8d191..8754a1ec6e042 100644 --- a/api_docs/kbn_deeplinks_observability.devdocs.json +++ b/api_docs/kbn_deeplinks_observability.devdocs.json @@ -30,7 +30,7 @@ "label": "AppId", "description": [], "signature": [ - "\"metrics\" | \"apm\" | \"logs\" | \"observability-overview\" | \"observabilityOnboarding\"" + "\"metrics\" | \"apm\" | \"logs\" | \"observability-overview\" | \"observabilityOnboarding\" | \"observability-log-explorer\"" ], "path": "packages/deeplinks/observability/deep_links.ts", "deprecated": false, @@ -52,7 +52,7 @@ "section": "def-common.AppId", "text": "AppId" }, - " | \"discover:log-explorer\" | \"logs:settings\" | \"logs:stream\" | \"logs:log-categories\" | \"logs:anomalies\" | \"observability-overview:cases\" | \"observability-overview:rules\" | \"observability-overview:alerts\" | \"observability-overview:cases_create\" | \"observability-overview:cases_configure\" | \"observability-overview:slos\" | \"metrics:settings\" | \"metrics:inventory\" | \"metrics:metrics-explorer\" | \"metrics:metrics-hosts\" | \"apm:traces\" | \"apm:dependencies\" | \"apm:service-map\" | \"apm:settings\" | \"apm:services\" | \"apm:service-groups-list\" | \"apm:storage-explorer\"" + " | \"logs:settings\" | \"logs:stream\" | \"logs:log-categories\" | \"logs:anomalies\" | \"observability-overview:cases\" | \"observability-overview:rules\" | \"observability-overview:alerts\" | \"observability-overview:cases_create\" | \"observability-overview:cases_configure\" | \"observability-overview:slos\" | \"metrics:settings\" | \"metrics:inventory\" | \"metrics:metrics-explorer\" | \"metrics:metrics-hosts\" | \"apm:traces\" | \"apm:dependencies\" | \"apm:service-map\" | \"apm:settings\" | \"apm:services\" | \"apm:service-groups-list\" | \"apm:storage-explorer\"" ], "path": "packages/deeplinks/observability/deep_links.ts", "deprecated": false, diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index 3acca01bbd93e..27aafd82955bc 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.devdocs.json b/api_docs/kbn_deeplinks_search.devdocs.json index a90271ae47ab3..bb431ec8a89e7 100644 --- a/api_docs/kbn_deeplinks_search.devdocs.json +++ b/api_docs/kbn_deeplinks_search.devdocs.json @@ -45,7 +45,7 @@ "label": "DeepLinkId", "description": [], "signature": [ - "\"serverlessElasticsearch\" | \"serverlessIndexingApi\" | \"serverlessConnectors\"" + "\"serverlessElasticsearch\" | \"serverlessConnectors\"" ], "path": "packages/deeplinks/search/deep_links.ts", "deprecated": false, @@ -69,13 +69,13 @@ }, { "parentPluginId": "@kbn/deeplinks-search", - "id": "def-common.SERVERLESS_ES_INDEXING_API_ID", + "id": "def-common.SERVERLESS_ES_CONNECTORS_ID", "type": "string", "tags": [], - "label": "SERVERLESS_ES_INDEXING_API_ID", + "label": "SERVERLESS_ES_CONNECTORS_ID", "description": [], "signature": [ - "\"serverlessIndexingApi\"" + "\"serverlessConnectors\"" ], "path": "packages/deeplinks/search/constants.ts", "deprecated": false, diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index cbdf9266b0f49..77c223bc20d19 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-08-25 +date: 2023-09-04 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 91188e3fc4d32..7264582d726e7 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-08-25 +date: 2023-09-04 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 45f18f23f9687..4250ff1f79e5b 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-08-25 +date: 2023-09-04 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 bad229e954b37..fae3d9e21e3c3 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-08-25 +date: 2023-09-04 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 4462b47b53f53..17782b1e88e9b 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-08-25 +date: 2023-09-04 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 6bfabaca472b0..dd3f81cb15c29 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-08-25 +date: 2023-09-04 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 c40284fab010f..f53155729fae3 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-08-25 +date: 2023-09-04 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 1750bf414522f..221d09cf8ce38 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_dev_utils.devdocs.json index 2d366c4839e72..6fa61e7f7047f 100644 --- a/api_docs/kbn_dev_utils.devdocs.json +++ b/api_docs/kbn_dev_utils.devdocs.json @@ -471,6 +471,34 @@ "initialIsOpen": false } ], - "objects": [] + "objects": [ + { + "parentPluginId": "@kbn/dev-utils", + "id": "def-common.kibanaDevServiceAccount", + "type": "Object", + "tags": [], + "label": "kibanaDevServiceAccount", + "description": [ + "\n`kibana-dev` service account token for connecting to ESS\nSee packages/kbn-es/src/ess_resources/README.md" + ], + "path": "packages/kbn-dev-utils/src/dev_service_account.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/dev-utils", + "id": "def-common.kibanaDevServiceAccount.token", + "type": "string", + "tags": [], + "label": "token", + "description": [], + "path": "packages/kbn-dev-utils/src/dev_service_account.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ] } } \ No newline at end of file diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 8a5b8636439b1..aa85a056e4e7d 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; @@ -21,10 +21,13 @@ Contact [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kiban | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 27 | 2 | 24 | 0 | +| 29 | 2 | 25 | 0 | ## Common +### Objects + + ### Functions diff --git a/api_docs/kbn_discover_utils.devdocs.json b/api_docs/kbn_discover_utils.devdocs.json index 6ae82d7acfccd..74196fab61cdd 100644 --- a/api_docs/kbn_discover_utils.devdocs.json +++ b/api_docs/kbn_discover_utils.devdocs.json @@ -587,6 +587,41 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.getFieldTypeName", + "type": "Function", + "tags": [], + "label": "getFieldTypeName", + "description": [ + "\nReturns a user-friendly name of a field type" + ], + "signature": [ + "(type: string | undefined) => string" + ], + "path": "packages/kbn-discover-utils/src/utils/get_field_type_name.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.getFieldTypeName.$1", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-discover-utils/src/utils/get_field_type_name.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/discover-utils", "id": "def-common.getIgnoredReason", @@ -744,6 +779,39 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.isKnownFieldType", + "type": "Function", + "tags": [], + "label": "isKnownFieldType", + "description": [], + "signature": [ + "(type?: string | undefined) => type is string" + ], + "path": "packages/kbn-discover-utils/src/utils/field_types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.isKnownFieldType.$1", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-discover-utils/src/utils/field_types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/discover-utils", "id": "def-common.isNestedFieldParent", @@ -875,6 +943,20 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.KNOWN_FIELD_TYPES", + "type": "Enum", + "tags": [], + "label": "KNOWN_FIELD_TYPES", + "description": [ + "\nField types for which name and description are defined" + ], + "path": "packages/kbn-discover-utils/src/utils/field_types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "misc": [ @@ -970,13 +1052,13 @@ }, { "parentPluginId": "@kbn/discover-utils", - "id": "def-common.ENABLE_SQL", + "id": "def-common.ENABLE_ESQL", "type": "string", "tags": [], - "label": "ENABLE_SQL", + "label": "ENABLE_ESQL", "description": [], "signature": [ - "\"discover:enableSql\"" + "\"discover:enableESQL\"" ], "path": "packages/kbn-discover-utils/src/constants.ts", "deprecated": false, @@ -1013,6 +1095,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.KNOWN_FIELD_TYPE_LIST", + "type": "Array", + "tags": [], + "label": "KNOWN_FIELD_TYPE_LIST", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/kbn-discover-utils/src/utils/field_types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/discover-utils", "id": "def-common.MAX_DOC_FIELDS_DISPLAYED", diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index 7ede5a3fa9e51..f94def353f5b9 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 59 | 0 | 34 | 3 | +| 65 | 0 | 38 | 3 | ## Common diff --git a/api_docs/kbn_doc_links.devdocs.json b/api_docs/kbn_doc_links.devdocs.json index 5dd70d02389dd..724a581015e7e 100644 --- a/api_docs/kbn_doc_links.devdocs.json +++ b/api_docs/kbn_doc_links.devdocs.json @@ -644,7 +644,7 @@ "label": "apis", "description": [], "signature": [ - "{ readonly bulkIndexAlias: string; readonly byteSizeUnits: string; readonly createAutoFollowPattern: string; readonly createFollower: string; readonly createIndex: string; readonly createSnapshotLifecyclePolicy: string; readonly createRoleMapping: string; readonly createRoleMappingTemplates: string; readonly createRollupJobsRequest: string; readonly createApiKey: string; readonly createPipeline: string; readonly createTransformRequest: string; readonly cronExpressions: string; readonly executeWatchActionModes: string; readonly indexExists: string; readonly multiSearch: string; readonly openIndex: string; readonly putComponentTemplate: string; readonly painlessExecute: string; readonly painlessExecuteAPIContexts: string; readonly putComponentTemplateMetadata: string; readonly putSnapshotLifecyclePolicy: string; readonly putIndexTemplateV1: string; readonly putWatch: string; readonly restApis: string; readonly searchPreference: string; readonly securityApis: string; readonly simulatePipeline: string; readonly timeUnits: string; readonly unfreezeIndex: string; readonly updateTransform: string; }" + "{ readonly bulkIndexAlias: string; readonly indexStats: string; readonly byteSizeUnits: string; readonly createAutoFollowPattern: string; readonly createFollower: string; readonly createIndex: string; readonly createSnapshotLifecyclePolicy: string; readonly createRoleMapping: string; readonly createRoleMappingTemplates: string; readonly createRollupJobsRequest: string; readonly createApiKey: string; readonly createPipeline: string; readonly createTransformRequest: string; readonly cronExpressions: string; readonly executeWatchActionModes: string; readonly indexExists: string; readonly multiSearch: string; readonly openIndex: string; readonly putComponentTemplate: string; readonly painlessExecute: string; readonly painlessExecuteAPIContexts: string; readonly putComponentTemplateMetadata: string; readonly putSnapshotLifecyclePolicy: string; readonly putIndexTemplateV1: string; readonly putWatch: string; readonly restApis: string; readonly searchPreference: string; readonly securityApis: string; readonly simulatePipeline: string; readonly timeUnits: string; readonly unfreezeIndex: string; readonly updateTransform: 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 ba508acd2f964..680d9b3b584ce 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-08-25 +date: 2023-09-04 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 f7d848a583e9f..fd1a6e57c4989 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-08-25 +date: 2023-09-04 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 22e3673cfcb19..841a5c4a07c1a 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-08-25 +date: 2023-09-04 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 ec2c683d5afaa..bfa79fd0c14be 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-08-25 +date: 2023-09-04 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 462c40ff449a1..e560475936e61 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-08-25 +date: 2023-09-04 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 7cae6dca9c0d7..a68749122ad5e 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_elastic_assistant.devdocs.json index e65b4e309784d..ba770f780e3fd 100644 --- a/api_docs/kbn_elastic_assistant.devdocs.json +++ b/api_docs/kbn_elastic_assistant.devdocs.json @@ -80,6 +80,43 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant", + "id": "def-public.AssistantAvatar", + "type": "Function", + "tags": [], + "label": "AssistantAvatar", + "description": [ + "\nDefault Elastic AI Assistant logo\n\nTODO: Can be removed once added to EUI" + ], + "signature": [ + "({ size }: ", + "AssistantAvatarProps", + ") => JSX.Element" + ], + "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_avatar/assistant_avatar.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant", + "id": "def-public.AssistantAvatar.$1", + "type": "Object", + "tags": [], + "label": "{ size = 's' }", + "description": [], + "signature": [ + "AssistantAvatarProps" + ], + "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_avatar/assistant_avatar.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant", "id": "def-public.AssistantOverlay", @@ -122,7 +159,7 @@ "label": "AssistantProvider", "description": [], "signature": [ - "({ actionTypeRegistry, assistantAvailability, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, baseAllowReplacement, defaultAllow, defaultAllowReplacement, docLinks, basePromptContexts, baseQuickPrompts, baseSystemPrompts, children, getComments, http, getInitialConversations, nameSpace, setConversations, setDefaultAllow, setDefaultAllowReplacement, title, }: React.PropsWithChildren<", + "({ actionTypeRegistry, assistantAvailability, assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, baseAllowReplacement, defaultAllow, defaultAllowReplacement, docLinks, basePromptContexts, baseQuickPrompts, baseSystemPrompts, children, getComments, http, getInitialConversations, nameSpace, setConversations, setDefaultAllow, setDefaultAllowReplacement, title, }: React.PropsWithChildren<", "AssistantProviderProps", ">) => JSX.Element" ], @@ -135,7 +172,7 @@ "id": "def-public.AssistantProvider.$1", "type": "CompoundType", "tags": [], - "label": "{\n actionTypeRegistry,\n assistantAvailability,\n assistantTelemetry,\n augmentMessageCodeBlocks,\n baseAllow,\n baseAllowReplacement,\n defaultAllow,\n defaultAllowReplacement,\n docLinks,\n basePromptContexts = [],\n baseQuickPrompts = [],\n baseSystemPrompts = BASE_SYSTEM_PROMPTS,\n children,\n getComments,\n http,\n getInitialConversations,\n nameSpace = DEFAULT_ASSISTANT_NAMESPACE,\n setConversations,\n setDefaultAllow,\n setDefaultAllowReplacement,\n title = DEFAULT_ASSISTANT_TITLE,\n}", + "label": "{\n actionTypeRegistry,\n assistantAvailability,\n assistantLangChain,\n assistantTelemetry,\n augmentMessageCodeBlocks,\n baseAllow,\n baseAllowReplacement,\n defaultAllow,\n defaultAllowReplacement,\n docLinks,\n basePromptContexts = [],\n baseQuickPrompts = [],\n baseSystemPrompts = BASE_SYSTEM_PROMPTS,\n children,\n getComments,\n http,\n getInitialConversations,\n nameSpace = DEFAULT_ASSISTANT_NAMESPACE,\n setConversations,\n setDefaultAllow,\n setDefaultAllowReplacement,\n title = DEFAULT_ASSISTANT_TITLE,\n}", "description": [], "signature": [ "React.PropsWithChildren<", diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index e70e9708088f2..f3848f7c863f6 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/secur | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 82 | 0 | 63 | 4 | +| 84 | 0 | 64 | 5 | ## Client diff --git a/api_docs/kbn_es.devdocs.json b/api_docs/kbn_es.devdocs.json index 7ae7cfcd31d0e..b7cfd2bbebb2e 100644 --- a/api_docs/kbn_es.devdocs.json +++ b/api_docs/kbn_es.devdocs.json @@ -19,6 +19,41 @@ "common": { "classes": [], "functions": [ + { + "parentPluginId": "@kbn/es", + "id": "def-common.getDockerFileMountPath", + "type": "Function", + "tags": [], + "label": "getDockerFileMountPath", + "description": [ + "\nRemoves REPO_ROOT from hostPath. Keep the rest to avoid filename collisions.\nReturns the path where a file will be mounted inside the ES or ESS container.\n/root/kibana/package/foo/bar.json => /usr/share/elasticsearch/files/package/foo/bar.json" + ], + "signature": [ + "(hostPath: string) => string" + ], + "path": "packages/kbn-es/src/utils/docker.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/es", + "id": "def-common.getDockerFileMountPath.$1", + "type": "string", + "tags": [], + "label": "hostPath", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-es/src/utils/docker.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/es", "id": "def-common.run", @@ -56,6 +91,36 @@ "interfaces": [], "enums": [], "misc": [ + { + "parentPluginId": "@kbn/es", + "id": "def-common.ELASTIC_SERVERLESS_SUPERUSER", + "type": "string", + "tags": [], + "label": "ELASTIC_SERVERLESS_SUPERUSER", + "description": [], + "signature": [ + "\"elastic_serverless\"" + ], + "path": "packages/kbn-es/src/utils/ess_file_realm.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/es", + "id": "def-common.ELASTIC_SERVERLESS_SUPERUSER_PASSWORD", + "type": "string", + "tags": [], + "label": "ELASTIC_SERVERLESS_SUPERUSER_PASSWORD", + "description": [], + "signature": [ + "\"changeme\"" + ], + "path": "packages/kbn-es/src/utils/ess_file_realm.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/es", "id": "def-common.SYSTEM_INDICES_SUPERUSER", diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 3ca050de0f20e..005fd3482096e 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kiban | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 4 | 0 | 4 | 0 | +| 8 | 0 | 7 | 0 | ## Common diff --git a/api_docs/kbn_es_archiver.devdocs.json b/api_docs/kbn_es_archiver.devdocs.json index 65257a15f067a..61d819e2b15f9 100644 --- a/api_docs/kbn_es_archiver.devdocs.json +++ b/api_docs/kbn_es_archiver.devdocs.json @@ -439,7 +439,7 @@ "tags": [], "label": "emptyKibanaIndex", "description": [ - "\nDelete any Kibana indices, and initialize the Kibana index as Kibana would do\non startup." + "\nCleanup saved object indices, preserving the space:default saved object." ], "signature": [ "() => Promise never" ], - "path": "packages/kbn-es-query/src/es_query/es_query_sql.ts", + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -2592,7 +2592,7 @@ "text": "AggregateQuery" } ], - "path": "packages/kbn-es-query/src/es_query/es_query_sql.ts", + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -2683,6 +2683,39 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/es-query", + "id": "def-common.getIndexPatternFromESQLQuery", + "type": "Function", + "tags": [], + "label": "getIndexPatternFromESQLQuery", + "description": [], + "signature": [ + "(esql: string | undefined) => string" + ], + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/es-query", + "id": "def-common.getIndexPatternFromESQLQuery.$1", + "type": "string", + "tags": [], + "label": "esql", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/es-query", "id": "def-common.getIndexPatternFromSQLQuery", @@ -2693,7 +2726,7 @@ "signature": [ "(sqlQuery: string | undefined) => string" ], - "path": "packages/kbn-es-query/src/es_query/es_query_sql.ts", + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -2707,7 +2740,7 @@ "signature": [ "string | undefined" ], - "path": "packages/kbn-es-query/src/es_query/es_query_sql.ts", + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", "deprecated": false, "trackAdoption": false, "isRequired": false @@ -2716,6 +2749,39 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/es-query", + "id": "def-common.getLanguageDisplayName", + "type": "Function", + "tags": [], + "label": "getLanguageDisplayName", + "description": [], + "signature": [ + "(language: string) => string" + ], + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/es-query", + "id": "def-common.getLanguageDisplayName.$1", + "type": "string", + "tags": [], + "label": "language", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/es-query", "id": "def-common.isCombinedFilter", @@ -3152,7 +3218,7 @@ }, " | { [key: string]: any; }) => boolean" ], - "path": "packages/kbn-es-query/src/es_query/es_query_sql.ts", + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -3181,7 +3247,7 @@ }, " | { [key: string]: any; }" ], - "path": "packages/kbn-es-query/src/es_query/es_query_sql.ts", + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -3216,7 +3282,7 @@ }, " | undefined) => boolean" ], - "path": "packages/kbn-es-query/src/es_query/es_query_sql.ts", + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -3245,7 +3311,7 @@ }, " | undefined" ], - "path": "packages/kbn-es-query/src/es_query/es_query_sql.ts", + "path": "packages/kbn-es-query/src/es_query/es_aggregate_query.ts", "deprecated": false, "trackAdoption": false, "isRequired": false diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 96dd4626146e9..e9517ca3104b5 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.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 | |-------------------|-----------|------------------------|-----------------| -| 255 | 1 | 195 | 15 | +| 259 | 1 | 199 | 15 | ## Common diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 7227fdb8a7b09..38b73a110ca77 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-08-25 +date: 2023-09-04 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 bb0c47998bc87..66abf444c8b53 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-08-25 +date: 2023-09-04 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 135c3ef55f74a..0a174e736f20c 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-08-25 +date: 2023-09-04 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 f522e5b8529a4..de0bd895c985f 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-08-25 +date: 2023-09-04 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 ec8995c7d11c7..13781f518b5ec 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-08-25 +date: 2023-09-04 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 4db58ac227b30..ad4a4b273e8e8 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 3c9daf3c843f1..00e0c7067898d 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-08-25 +date: 2023-09-04 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 b4deb77ddadda..0914a65226a78 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-08-25 +date: 2023-09-04 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 b7068762d7ae8..ac8fe1cfaaece 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-08-25 +date: 2023-09-04 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 fd5f027516ce9..36d70609fff30 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index 6c76a0d147a2b..535a346008b2a 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_generate_csv_types.mdx b/api_docs/kbn_generate_csv_types.mdx index e71fc66b2a4ca..52f09760733c6 100644 --- a/api_docs/kbn_generate_csv_types.mdx +++ b/api_docs/kbn_generate_csv_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv-types title: "@kbn/generate-csv-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv-types plugin -date: 2023-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv-types'] --- import kbnGenerateCsvTypesObj from './kbn_generate_csv_types.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 09ccfecc055cb..a84641b1f31f3 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-08-25 +date: 2023-09-04 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 a236a6b0de35a..b3432765d2cf7 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-08-25 +date: 2023-09-04 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 aec7b0fafa8c4..df9387df99a45 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-08-25 +date: 2023-09-04 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 18cbaa43c90df..ea08a7056e52e 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-08-25 +date: 2023-09-04 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 40921849a82c5..19b54388f1519 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-08-25 +date: 2023-09-04 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 fb89ad9f59872..a81cc773aa125 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-08-25 +date: 2023-09-04 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 bcbcf851deacb..8b3a393006f29 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-08-25 +date: 2023-09-04 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 99abc42a7b8f9..b4c6a755874f1 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-08-25 +date: 2023-09-04 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 2f6e2c4184dc6..cf05dbcd99a9f 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-08-25 +date: 2023-09-04 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 4b21f5bd73d67..8b0b0c72627dd 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-08-25 +date: 2023-09-04 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 182598d8a2f6c..7082d4f9a7ba9 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.devdocs.json b/api_docs/kbn_io_ts_utils.devdocs.json index 06b7c2f9c5137..76c85df71d2fb 100644 --- a/api_docs/kbn_io_ts_utils.devdocs.json +++ b/api_docs/kbn_io_ts_utils.devdocs.json @@ -228,14 +228,14 @@ " | ", "ParseableType", ") => ", + "StringType", + " | ", "Type", " | ", - "StringType", + "NumberType", " | ", "BooleanType", " | ", - "NumberType", - " | ", "RecordC", "<", "Mixed", diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 3850f0432d364..a33f58b9fcc80 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-08-25 +date: 2023-09-04 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 94156b4bb1c68..5c5c6dfcc83ba 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-08-25 +date: 2023-09-04 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 511b0fd655c8f..65e521ce86076 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-08-25 +date: 2023-09-04 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 da1fdaaa7c71a..2e345b7349536 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-08-25 +date: 2023-09-04 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 1e7d8f3f91cb6..70cc72bd8509a 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-08-25 +date: 2023-09-04 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 c12c9f758e221..a9aac7c0659f0 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-08-25 +date: 2023-09-04 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 56bfd5db613a5..9bf8ce9d546a4 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-08-25 +date: 2023-09-04 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 f58fbc84f2a58..de2011a628ca0 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-08-25 +date: 2023-09-04 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 f14dfa14d65ba..711e440bfc5f8 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-08-25 +date: 2023-09-04 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 658ae2ae23ac2..3cb969be0abb7 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-08-25 +date: 2023-09-04 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 55dd46bc6a084..6e26100fbc321 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-08-25 +date: 2023-09-04 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_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index 745551602a8ad..7d191045ebc7d 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-08-25 +date: 2023-09-04 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_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index 17bfa0090db05..d2eae1d7bce9a 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.devdocs.json b/api_docs/kbn_mapbox_gl.devdocs.json index 5c5fb82b56b43..a719d22f94a26 100644 --- a/api_docs/kbn_mapbox_gl.devdocs.json +++ b/api_docs/kbn_mapbox_gl.devdocs.json @@ -9443,7 +9443,7 @@ "label": "MapEvent", "description": [], "signature": [ - "\"error\" | \"remove\" | \"data\" | \"render\" | \"rotate\" | \"resize\" | \"zoom\" | \"move\" | \"idle\" | \"mousedown\" | \"mouseup\" | \"mouseover\" | \"mousemove\" | \"click\" | \"dblclick\" | \"mouseenter\" | \"mouseleave\" | \"mouseout\" | \"contextmenu\" | \"wheel\" | \"touchstart\" | \"touchend\" | \"touchmove\" | \"touchcancel\" | \"movestart\" | \"moveend\" | \"dragstart\" | \"drag\" | \"dragend\" | \"zoomstart\" | \"zoomend\" | \"rotatestart\" | \"rotateend\" | \"pitchstart\" | \"pitch\" | \"pitchend\" | \"boxzoomstart\" | \"boxzoomend\" | \"boxzoomcancel\" | \"webglcontextlost\" | \"webglcontextrestored\" | \"load\" | \"styledata\" | \"sourcedata\" | \"dataloading\" | \"styledataloading\" | \"sourcedataloading\" | \"styleimagemissing\" | \"style.load\" | \"terrain\" | \"dataabort\" | \"sourcedataabort\"" + "\"error\" | \"remove\" | \"data\" | \"rotate\" | \"render\" | \"resize\" | \"zoom\" | \"move\" | \"idle\" | \"mousedown\" | \"mouseup\" | \"mouseover\" | \"mousemove\" | \"click\" | \"dblclick\" | \"mouseenter\" | \"mouseleave\" | \"mouseout\" | \"contextmenu\" | \"wheel\" | \"touchstart\" | \"touchend\" | \"touchmove\" | \"touchcancel\" | \"movestart\" | \"moveend\" | \"dragstart\" | \"drag\" | \"dragend\" | \"zoomstart\" | \"zoomend\" | \"rotatestart\" | \"rotateend\" | \"pitchstart\" | \"pitch\" | \"pitchend\" | \"boxzoomstart\" | \"boxzoomend\" | \"boxzoomcancel\" | \"webglcontextlost\" | \"webglcontextrestored\" | \"load\" | \"styledata\" | \"sourcedata\" | \"dataloading\" | \"styledataloading\" | \"sourcedataloading\" | \"styleimagemissing\" | \"style.load\" | \"terrain\" | \"dataabort\" | \"sourcedataabort\"" ], "path": "node_modules/maplibre-gl/dist/maplibre-gl.d.ts", "deprecated": false, diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 4daf6e0ea1408..1fdc4c51c3650 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-08-25 +date: 2023-09-04 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 cab61e0f69eae..58f7939ca5d5e 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-08-25 +date: 2023-09-04 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 7fc81004e2957..691cb37fbf092 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-08-25 +date: 2023-09-04 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 691a71390a8e2..eee5c0c2f957c 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-08-25 +date: 2023-09-04 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 79b76af765de4..25035040db3b1 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-08-25 +date: 2023-09-04 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_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index a157bc49ef3b8..760d63a13479d 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-08-25 +date: 2023-09-04 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 8aa5d97acdc42..91fd1d78dddcc 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-08-25 +date: 2023-09-04 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 2c3990b041a97..9a7b632bfc239 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-08-25 +date: 2023-09-04 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 fcd6cc205066f..c62bb1d107814 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-08-25 +date: 2023-09-04 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 f883c8ec88b2c..01a7da5e0fe1a 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-08-25 +date: 2023-09-04 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 2a07549f4697b..aa913fde4e88e 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-08-25 +date: 2023-09-04 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 fe7b1dc43437a..0c835d13abcc0 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-08-25 +date: 2023-09-04 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 7834857f7825f..cc78ed0a4b7ae 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-08-25 +date: 2023-09-04 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 0e1ac627fdadd..107c55eb0c7ac 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-08-25 +date: 2023-09-04 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 15870f5847327..2065ae3bc39cb 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-08-25 +date: 2023-09-04 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 9b52ad48be606..a4eee0f82e0b9 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-08-25 +date: 2023-09-04 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 72a1af18d9a8e..3034ca61406aa 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-08-25 +date: 2023-09-04 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 81ea7b6d27815..a0469d94ac6e7 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-08-25 +date: 2023-09-04 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 57b2d6f1a6040..4710c74dc5db0 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-08-25 +date: 2023-09-04 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 dc136b6284173..41f5c96969e43 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-08-25 +date: 2023-09-04 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 3e53243c9c28b..272f1ec79a7e3 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-08-25 +date: 2023-09-04 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 ac0ef0d886390..7196a47871adc 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-08-25 +date: 2023-09-04 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 51a484c01a0bc..268506be5de99 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-08-25 +date: 2023-09-04 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 52d191316b87e..6233c2ff21886 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-08-25 +date: 2023-09-04 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 364fa6046fc99..a02324fc33509 100644 --- a/api_docs/kbn_monaco.devdocs.json +++ b/api_docs/kbn_monaco.devdocs.json @@ -373,7 +373,7 @@ "label": "getSourceIdentifiers", "description": [], "signature": [ - "CallbackFn | undefined" + "CallbackFn | undefined" ], "path": "packages/kbn-monaco/src/esql/lib/autocomplete/types.ts", "deprecated": false, @@ -387,7 +387,49 @@ "label": "getFieldsIdentifiers", "description": [], "signature": [ - "CallbackFn | undefined" + "CallbackFn | undefined" + ], + "path": "packages/kbn-monaco/src/esql/lib/autocomplete/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/monaco", + "id": "def-common.ESQLCustomAutocompleteCallbacks.getPoliciesIdentifiers", + "type": "Function", + "tags": [], + "label": "getPoliciesIdentifiers", + "description": [], + "signature": [ + "CallbackFn<{ name: string; indices: string[]; }> | undefined" + ], + "path": "packages/kbn-monaco/src/esql/lib/autocomplete/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/monaco", + "id": "def-common.ESQLCustomAutocompleteCallbacks.getPolicyFieldsIdentifiers", + "type": "Function", + "tags": [], + "label": "getPolicyFieldsIdentifiers", + "description": [], + "signature": [ + "CallbackFn | undefined" + ], + "path": "packages/kbn-monaco/src/esql/lib/autocomplete/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/monaco", + "id": "def-common.ESQLCustomAutocompleteCallbacks.getPolicyMatchingFieldIdentifiers", + "type": "Function", + "tags": [], + "label": "getPolicyMatchingFieldIdentifiers", + "description": [], + "signature": [ + "CallbackFn | undefined" ], "path": "packages/kbn-monaco/src/esql/lib/autocomplete/types.ts", "deprecated": false, diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 1502f46a0ce1f..006a6f6cec754 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.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 | |-------------------|-----------|------------------------|-----------------| -| 71 | 0 | 69 | 3 | +| 74 | 0 | 72 | 3 | ## Common diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index 0c69b237614b5..bbf4cff07dd56 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-08-25 +date: 2023-09-04 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 842080bfa51ce..fe0ec9ae2be57 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2023-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 17a09867068c1..97458320821c4 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-08-25 +date: 2023-09-04 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 2e9f296b90b31..fbb3acd670442 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index d2e973fb001ca..3051e6d9f202d 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 4cf5019880d81..65eb12fabc001 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-08-25 +date: 2023-09-04 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 a559cfabaa7b2..2e7ae7cd612d2 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-08-25 +date: 2023-09-04 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 29e5abaa7b481..1f6b1674c1b57 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index 4c0b9355640c2..d6124aaa74fc8 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-08-25 +date: 2023-09-04 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 1697549cc4bb6..7c926ea4c4986 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-08-25 +date: 2023-09-04 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 e8d85c7cacf95..8db67fd4505c6 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-08-25 +date: 2023-09-04 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 45bc588d747d6..d1a19a7e513e3 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-08-25 +date: 2023-09-04 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 9adabd3e40dca..7a45bc910bf2a 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-08-25 +date: 2023-09-04 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 4da8f639f3dbd..38fed573cdfc0 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-08-25 +date: 2023-09-04 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 b395a54869f45..cb6552e865624 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-08-25 +date: 2023-09-04 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 5e228ab7a2873..eb89b1c4fffec 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-08-25 +date: 2023-09-04 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 6aa815dd14810..5f4e54cae6099 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-08-25 +date: 2023-09-04 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 8a4fad737fc29..2da515748dd5c 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-08-25 +date: 2023-09-04 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 feb350ca058ca..250aa6f45d7a7 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-08-25 +date: 2023-09-04 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 8951e31d86ae6..c6b17080d62a8 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index 8bdef648ce860..8e49b829556ba 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 576752ee5dacd..bcfaa8de5ef1c 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-08-25 +date: 2023-09-04 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 62b689ad7a0ad..14310b52decfe 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index cd0db4184f021..d045834c6decb 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-08-25 +date: 2023-09-04 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 bc43addc08301..294015e805f0c 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_search_api_panels.devdocs.json index 61387ae067fa3..8c1ce9f259ef6 100644 --- a/api_docs/kbn_search_api_panels.devdocs.json +++ b/api_docs/kbn_search_api_panels.devdocs.json @@ -27,7 +27,7 @@ "label": "CodeBox", "description": [], "signature": [ - "({ application, codeSnippet, http, languageType, languages, pluginId, selectedLanguage, setSelectedLanguage, sharePlugin, showTryInConsole, }: React.PropsWithChildren) => JSX.Element" + "({ application, codeSnippet, languageType, languages, assetBasePath, selectedLanguage, setSelectedLanguage, sharePlugin, consoleRequest, }: React.PropsWithChildren) => JSX.Element" ], "path": "packages/kbn-search-api-panels/components/code_box.tsx", "deprecated": false, @@ -38,7 +38,7 @@ "id": "def-common.CodeBox.$1", "type": "CompoundType", "tags": [], - "label": "{\n application,\n codeSnippet,\n http,\n languageType,\n languages,\n pluginId,\n selectedLanguage,\n setSelectedLanguage,\n sharePlugin,\n showTryInConsole,\n}", + "label": "{\n application,\n codeSnippet,\n languageType,\n languages,\n assetBasePath,\n selectedLanguage,\n setSelectedLanguage,\n sharePlugin,\n consoleRequest,\n}", "description": [], "signature": [ "React.PropsWithChildren" @@ -52,6 +52,54 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.getConsoleRequest", + "type": "Function", + "tags": [], + "label": "getConsoleRequest", + "description": [], + "signature": [ + "(code: keyof ", + { + "pluginId": "@kbn/search-api-panels", + "scope": "common", + "docId": "kibKbnSearchApiPanelsPluginApi", + "section": "def-common.LanguageDefinition", + "text": "LanguageDefinition" + }, + ") => string | undefined" + ], + "path": "packages/kbn-search-api-panels/utils.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.getConsoleRequest.$1", + "type": "CompoundType", + "tags": [], + "label": "code", + "description": [], + "signature": [ + "keyof ", + { + "pluginId": "@kbn/search-api-panels", + "scope": "common", + "docId": "kibKbnSearchApiPanelsPluginApi", + "section": "def-common.LanguageDefinition", + "text": "LanguageDefinition" + } + ], + "path": "packages/kbn-search-api-panels/utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/search-api-panels", "id": "def-common.getLanguageDefinitionCodeSnippet", @@ -168,15 +216,7 @@ "label": "GithubLink", "description": [], "signature": [ - "({ label, href, http, pluginId }: React.PropsWithChildren<{ label: string; href: string; http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; pluginId: string; }>) => JSX.Element" + "({ assetBasePath, label, href }: React.PropsWithChildren<{ assetBasePath: string; label: string; href: string; }>) => JSX.Element" ], "path": "packages/kbn-search-api-panels/components/github_link.tsx", "deprecated": false, @@ -187,18 +227,10 @@ "id": "def-common.GithubLink.$1", "type": "CompoundType", "tags": [], - "label": "{ label, href, http, pluginId }", + "label": "{ assetBasePath, label, href }", "description": [], "signature": [ - "React.PropsWithChildren<{ label: string; href: string; http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; pluginId: string; }>" + "React.PropsWithChildren<{ assetBasePath: string; label: string; href: string; }>" ], "path": "packages/kbn-search-api-panels/components/github_link.tsx", "deprecated": false, @@ -217,7 +249,7 @@ "label": "IngestData", "description": [], "signature": [ - "({ codeSnippet, selectedLanguage, setSelectedLanguage, docLinks, http, pluginId, application, sharePlugin, languages, showTryInConsole, }: React.PropsWithChildren) => JSX.Element" + "({ codeSnippet, selectedLanguage, setSelectedLanguage, docLinks, assetBasePath, application, sharePlugin, languages, consoleRequest, }: React.PropsWithChildren) => JSX.Element" ], "path": "packages/kbn-search-api-panels/components/ingest_data.tsx", "deprecated": false, @@ -228,7 +260,7 @@ "id": "def-common.IngestData.$1", "type": "CompoundType", "tags": [], - "label": "{\n codeSnippet,\n selectedLanguage,\n setSelectedLanguage,\n docLinks,\n http,\n pluginId,\n application,\n sharePlugin,\n languages,\n showTryInConsole,\n}", + "label": "{\n codeSnippet,\n selectedLanguage,\n setSelectedLanguage,\n docLinks,\n assetBasePath,\n application,\n sharePlugin,\n languages,\n consoleRequest,\n}", "description": [], "signature": [ "React.PropsWithChildren" @@ -250,7 +282,7 @@ "label": "InstallClientPanel", "description": [], "signature": [ - "({ codeSnippet, showTryInConsole, language, languages, setSelectedLanguage, http, pluginId, application, sharePlugin, isPanelLeft, overviewPanelProps, }: React.PropsWithChildren) => JSX.Element" + "({ codeSnippet, consoleRequest, language, languages, setSelectedLanguage, assetBasePath, application, sharePlugin, isPanelLeft, overviewPanelProps, }: React.PropsWithChildren) => JSX.Element" ], "path": "packages/kbn-search-api-panels/components/install_client.tsx", "deprecated": false, @@ -261,7 +293,7 @@ "id": "def-common.InstallClientPanel.$1", "type": "CompoundType", "tags": [], - "label": "{\n codeSnippet,\n showTryInConsole,\n language,\n languages,\n setSelectedLanguage,\n http,\n pluginId,\n application,\n sharePlugin,\n isPanelLeft = true,\n overviewPanelProps,\n}", + "label": "{\n codeSnippet,\n consoleRequest,\n language,\n languages,\n setSelectedLanguage,\n assetBasePath,\n application,\n sharePlugin,\n isPanelLeft = true,\n overviewPanelProps,\n}", "description": [], "signature": [ "React.PropsWithChildren" @@ -283,7 +315,7 @@ "label": "IntegrationsPanel", "description": [], "signature": [ - "({ docLinks, http, pluginId, }: React.PropsWithChildren<", + "({ docLinks, assetBasePath, }: React.PropsWithChildren<", { "pluginId": "@kbn/search-api-panels", "scope": "common", @@ -302,7 +334,7 @@ "id": "def-common.IntegrationsPanel.$1", "type": "CompoundType", "tags": [], - "label": "{\n docLinks,\n http,\n pluginId,\n}", + "label": "{\n docLinks,\n assetBasePath,\n}", "description": [], "signature": [ "React.PropsWithChildren<", @@ -332,7 +364,7 @@ "label": "LanguageClientPanel", "description": [], "signature": [ - "({ language, setSelectedLanguage, isSelectedLanguage, http, pluginId, src, }: React.PropsWithChildren) => JSX.Element" + "({ language, setSelectedLanguage, isSelectedLanguage, assetBasePath, src, }: React.PropsWithChildren) => JSX.Element" ], "path": "packages/kbn-search-api-panels/components/language_client_panel.tsx", "deprecated": false, @@ -343,7 +375,7 @@ "id": "def-common.LanguageClientPanel.$1", "type": "CompoundType", "tags": [], - "label": "{\n language,\n setSelectedLanguage,\n isSelectedLanguage,\n http,\n pluginId,\n src,\n}", + "label": "{\n language,\n setSelectedLanguage,\n isSelectedLanguage,\n assetBasePath,\n src,\n}", "description": [], "signature": [ "React.PropsWithChildren" @@ -551,32 +583,12 @@ { "parentPluginId": "@kbn/search-api-panels", "id": "def-common.IntegrationsPanelProps.docLinks", - "type": "Any", - "tags": [], - "label": "docLinks", - "description": [], - "signature": [ - "any" - ], - "path": "packages/kbn-search-api-panels/components/integrations_panel.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/search-api-panels", - "id": "def-common.IntegrationsPanelProps.http", "type": "Object", "tags": [], - "label": "http", + "label": "docLinks", "description": [], "signature": [ - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - } + "{ beats: string; connectors: string; logstash: string; }" ], "path": "packages/kbn-search-api-panels/components/integrations_panel.tsx", "deprecated": false, @@ -584,10 +596,10 @@ }, { "parentPluginId": "@kbn/search-api-panels", - "id": "def-common.IntegrationsPanelProps.pluginId", + "id": "def-common.IntegrationsPanelProps.assetBasePath", "type": "string", "tags": [], - "label": "pluginId", + "label": "assetBasePath", "description": [], "path": "packages/kbn-search-api-panels/components/integrations_panel.tsx", "deprecated": false, @@ -900,6 +912,20 @@ "path": "packages/kbn-search-api-panels/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.LanguageDefinitionSnippetArguments.cloudId", + "type": "string", + "tags": [], + "label": "cloudId", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-search-api-panels/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index 93cf018aff906..eb04761a5bedd 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/te | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 63 | 1 | 63 | 0 | +| 65 | 0 | 65 | 0 | ## Common diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index ef834a4610a68..59dd53bdd24e4 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_security_solution_features.devdocs.json new file mode 100644 index 0000000000000..efeb01d3237a1 --- /dev/null +++ b/api_docs/kbn_security_solution_features.devdocs.json @@ -0,0 +1,487 @@ +{ + "id": "@kbn/security-solution-features", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeatureParams", + "type": "Interface", + "tags": [], + "label": "AppFeatureParams", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.AppFeatureParams", + "text": "AppFeatureParams" + }, + "" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeatureParams.baseKibanaFeature", + "type": "Object", + "tags": [], + "label": "baseKibanaFeature", + "description": [], + "signature": [ + "{ id: string; order?: number | undefined; name: string; alerting?: readonly string[] | undefined; cases?: readonly string[] | undefined; description?: string | undefined; category: ", + { + "pluginId": "@kbn/core-application-common", + "scope": "common", + "docId": "kibKbnCoreApplicationCommonPluginApi", + "section": "def-common.AppCategory", + "text": "AppCategory" + }, + "; management?: { [sectionId: string]: readonly string[]; } | undefined; privileges: { all: ", + { + "pluginId": "features", + "scope": "common", + "docId": "kibFeaturesPluginApi", + "section": "def-common.FeatureKibanaPrivileges", + "text": "FeatureKibanaPrivileges" + }, + "; read: ", + { + "pluginId": "features", + "scope": "common", + "docId": "kibFeaturesPluginApi", + "section": "def-common.FeatureKibanaPrivileges", + "text": "FeatureKibanaPrivileges" + }, + "; } | null; catalogue?: readonly string[] | undefined; excludeFromBasePrivileges?: boolean | undefined; minimumLicense?: \"basic\" | \"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\" | undefined; app: readonly string[]; privilegesTooltip?: string | undefined; reserved?: { description: string; privileges: readonly ", + "ReservedKibanaPrivilege", + "[]; } | undefined; }" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeatureParams.baseKibanaSubFeatureIds", + "type": "Array", + "tags": [], + "label": "baseKibanaSubFeatureIds", + "description": [], + "signature": [ + "T[]" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeatureParams.subFeaturesMap", + "type": "Object", + "tags": [], + "label": "subFeaturesMap", + "description": [], + "signature": [ + "Map" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeatureKeys", + "type": "Type", + "tags": [], + "label": "AppFeatureKeys", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.AppFeatureKeyType", + "text": "AppFeatureKeyType" + }, + "[]" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeatureKeyType", + "type": "Type", + "tags": [], + "label": "AppFeatureKeyType", + "description": [], + "signature": [ + "AppFeatureSecurityKey", + " | ", + "AppFeatureCasesKey", + " | ", + "AppFeatureAssistantKey" + ], + "path": "x-pack/packages/security-solution/features/src/app_features_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeatureKibanaConfig", + "type": "Type", + "tags": [], + "label": "AppFeatureKibanaConfig", + "description": [], + "signature": [ + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "<", + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.BaseKibanaFeatureConfig", + "text": "BaseKibanaFeatureConfig" + }, + "> & { subFeatureIds?: T[] | undefined; subFeaturesPrivileges?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "<", + { + "pluginId": "features", + "scope": "common", + "docId": "kibFeaturesPluginApi", + "section": "def-common.SubFeaturePrivilegeConfig", + "text": "SubFeaturePrivilegeConfig" + }, + ">[] | undefined; }" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeaturesAssistantConfig", + "type": "Type", + "tags": [], + "label": "AppFeaturesAssistantConfig", + "description": [], + "signature": [ + "Map<", + "AppFeatureAssistantKey", + ", ", + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.AppFeatureKibanaConfig", + "text": "AppFeatureKibanaConfig" + }, + "<", + "AssistantSubFeatureId", + ">>" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeaturesCasesConfig", + "type": "Type", + "tags": [], + "label": "AppFeaturesCasesConfig", + "description": [], + "signature": [ + "Map<", + "AppFeatureCasesKey", + ", ", + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.AppFeatureKibanaConfig", + "text": "AppFeatureKibanaConfig" + }, + "<", + "CasesSubFeatureId", + ">>" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeaturesConfig", + "type": "Type", + "tags": [], + "label": "AppFeaturesConfig", + "description": [], + "signature": [ + "Map<", + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.AppFeatureKeyType", + "text": "AppFeatureKeyType" + }, + ", ", + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.AppFeatureKibanaConfig", + "text": "AppFeatureKibanaConfig" + }, + ">" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppFeaturesSecurityConfig", + "type": "Type", + "tags": [], + "label": "AppFeaturesSecurityConfig", + "description": [], + "signature": [ + "Map<", + "AppFeatureSecurityKey", + ", ", + { + "pluginId": "@kbn/security-solution-features", + "scope": "common", + "docId": "kibKbnSecuritySolutionFeaturesPluginApi", + "section": "def-common.AppFeatureKibanaConfig", + "text": "AppFeatureKibanaConfig" + }, + "<", + "SecuritySubFeatureId", + ">>" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.AppSubFeaturesMap", + "type": "Type", + "tags": [], + "label": "AppSubFeaturesMap", + "description": [], + "signature": [ + "Map" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.BaseKibanaFeatureConfig", + "type": "Type", + "tags": [], + "label": "BaseKibanaFeatureConfig", + "description": [], + "signature": [ + "{ id: string; order?: number | undefined; name: string; alerting?: readonly string[] | undefined; cases?: readonly string[] | undefined; description?: string | undefined; category: ", + { + "pluginId": "@kbn/core-application-common", + "scope": "common", + "docId": "kibKbnCoreApplicationCommonPluginApi", + "section": "def-common.AppCategory", + "text": "AppCategory" + }, + "; management?: { [sectionId: string]: readonly string[]; } | undefined; privileges: { all: ", + { + "pluginId": "features", + "scope": "common", + "docId": "kibFeaturesPluginApi", + "section": "def-common.FeatureKibanaPrivileges", + "text": "FeatureKibanaPrivileges" + }, + "; read: ", + { + "pluginId": "features", + "scope": "common", + "docId": "kibFeaturesPluginApi", + "section": "def-common.FeatureKibanaPrivileges", + "text": "FeatureKibanaPrivileges" + }, + "; } | null; catalogue?: readonly string[] | undefined; excludeFromBasePrivileges?: boolean | undefined; minimumLicense?: \"basic\" | \"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\" | undefined; app: readonly string[]; privilegesTooltip?: string | undefined; reserved?: { description: string; privileges: readonly ", + "ReservedKibanaPrivilege", + "[]; } | undefined; }" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-features", + "id": "def-common.SubFeaturesPrivileges", + "type": "Type", + "tags": [], + "label": "SubFeaturesPrivileges", + "description": [], + "signature": [ + "{ id?: string | undefined; name?: string | undefined; includeIn?: \"none\" | \"read\" | \"all\" | undefined; minimumLicense?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "<\"basic\" | \"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\" | undefined>; alerting?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "<{ rule?: { all?: readonly string[] | undefined; read?: readonly string[] | undefined; } | undefined; alert?: { all?: readonly string[] | undefined; read?: readonly string[] | undefined; } | undefined; } | undefined>; cases?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "<{ all?: readonly string[] | undefined; push?: readonly string[] | undefined; create?: readonly string[] | undefined; read?: readonly string[] | undefined; update?: readonly string[] | undefined; delete?: readonly string[] | undefined; } | undefined>; disabled?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "; management?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "<{ [sectionId: string]: readonly string[]; } | undefined>; ui?: readonly string[] | undefined; catalogue?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "; app?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "; requireAllSpaces?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "; api?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "; savedObject?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "<{ all: readonly string[]; read: readonly string[]; }> | undefined; }" + ], + "path": "x-pack/packages/security-solution/features/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx new file mode 100644 index 0000000000000..e77b728a2f4e4 --- /dev/null +++ b/api_docs/kbn_security_solution_features.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: kibKbnSecuritySolutionFeaturesPluginApi +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-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] +--- +import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; + + + +Contact [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 14 | 0 | 14 | 6 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index e81fa0a9618c9..7043cf400e960 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-08-25 +date: 2023-09-04 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 e053b5ae8b608..ceb844bb8248b 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-08-25 +date: 2023-09-04 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 4b2f16473c6d5..974630724490f 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-08-25 +date: 2023-09-04 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 cfc25f8fc18be..549718823ae00 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-08-25 +date: 2023-09-04 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 5ea8eb972cfe1..bcd3688220db7 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-08-25 +date: 2023-09-04 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 ab390fb03084b..b8ac39ed3aac3 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_securitysolution_es_utils.devdocs.json index 89a04e0c6a4a4..ffa1a41949e97 100644 --- a/api_docs/kbn_securitysolution_es_utils.devdocs.json +++ b/api_docs/kbn_securitysolution_es_utils.devdocs.json @@ -3819,6 +3819,39 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.stringifyZodError", + "type": "Function", + "tags": [], + "label": "stringifyZodError", + "description": [], + "signature": [ + "(err: Zod.ZodError) => string" + ], + "path": "packages/kbn-securitysolution-es-utils/src/transform_error/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.stringifyZodError.$1", + "type": "Object", + "tags": [], + "label": "err", + "description": [], + "signature": [ + "Zod.ZodError" + ], + "path": "packages/kbn-securitysolution-es-utils/src/transform_error/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-es-utils", "id": "def-common.transformError", diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 26c387644bdd1..8a06350968685 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-detection-engine](https://github.com/orgs/elastic/tea | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 87 | 0 | 76 | 1 | +| 89 | 0 | 78 | 1 | ## Common diff --git a/api_docs/kbn_securitysolution_exception_list_components.devdocs.json b/api_docs/kbn_securitysolution_exception_list_components.devdocs.json index e590d21733685..0b11d9dedc1c3 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.devdocs.json +++ b/api_docs/kbn_securitysolution_exception_list_components.devdocs.json @@ -834,7 +834,7 @@ "label": "formattedDateComponent", "description": [], "signature": [ - "\"symbol\" | \"object\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"source\" | \"desc\" | \"filter\" | \"text\" | \"map\" | \"head\" | React.ComponentType | \"slot\" | \"style\" | \"title\" | \"meta\" | \"pattern\" | \"summary\" | \"template\" | \"span\" | \"main\" | \"path\" | \"form\" | \"body\" | \"q\" | \"label\" | \"data\" | \"progress\" | \"legend\" | \"article\" | \"image\" | \"menu\" | \"stop\" | \"base\" | \"s\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"canvas\" | \"svg\" | \"select\" | \"output\" | \"script\" | \"time\" | \"mask\" | \"input\" | \"section\" | \"circle\" | \"code\" | \"line\" | \"area\" | \"animate\" | \"view\" | \"var\" | \"html\" | \"a\" | \"img\" | \"audio\" | \"br\" | \"clipPath\" | \"textarea\" | \"abbr\" | \"address\" | \"aside\" | \"b\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"button\" | \"caption\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"ins\" | \"kbd\" | \"keygen\" | \"li\" | \"mark\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"param\" | \"picture\" | \"pre\" | \"rp\" | \"rt\" | \"ruby\" | \"samp\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"video\" | \"wbr\" | \"webview\" | \"animateMotion\" | \"animateTransform\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"linearGradient\" | \"marker\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\"" + "\"symbol\" | \"object\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"source\" | \"desc\" | \"filter\" | \"text\" | \"map\" | \"head\" | React.ComponentType | \"slot\" | \"style\" | \"title\" | \"meta\" | \"pattern\" | \"summary\" | \"template\" | \"span\" | \"main\" | \"path\" | \"form\" | \"body\" | \"q\" | \"label\" | \"data\" | \"progress\" | \"legend\" | \"article\" | \"image\" | \"menu\" | \"stop\" | \"base\" | \"s\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"canvas\" | \"svg\" | \"select\" | \"output\" | \"script\" | \"time\" | \"mask\" | \"input\" | \"clipPath\" | \"section\" | \"circle\" | \"code\" | \"line\" | \"area\" | \"animate\" | \"view\" | \"var\" | \"html\" | \"a\" | \"img\" | \"audio\" | \"br\" | \"textarea\" | \"abbr\" | \"address\" | \"aside\" | \"b\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"button\" | \"caption\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"ins\" | \"kbd\" | \"keygen\" | \"li\" | \"mark\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"param\" | \"picture\" | \"pre\" | \"rp\" | \"rt\" | \"ruby\" | \"samp\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"video\" | \"wbr\" | \"webview\" | \"animateMotion\" | \"animateTransform\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"linearGradient\" | \"marker\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\"" ], "path": "packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx", "deprecated": false, @@ -848,7 +848,7 @@ "label": "securityLinkAnchorComponent", "description": [], "signature": [ - "\"symbol\" | \"object\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"source\" | \"desc\" | \"filter\" | \"text\" | \"map\" | \"head\" | React.ComponentType | \"slot\" | \"style\" | \"title\" | \"meta\" | \"pattern\" | \"summary\" | \"template\" | \"span\" | \"main\" | \"path\" | \"form\" | \"body\" | \"q\" | \"label\" | \"data\" | \"progress\" | \"legend\" | \"article\" | \"image\" | \"menu\" | \"stop\" | \"base\" | \"s\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"canvas\" | \"svg\" | \"select\" | \"output\" | \"script\" | \"time\" | \"mask\" | \"input\" | \"section\" | \"circle\" | \"code\" | \"line\" | \"area\" | \"animate\" | \"view\" | \"var\" | \"html\" | \"a\" | \"img\" | \"audio\" | \"br\" | \"clipPath\" | \"textarea\" | \"abbr\" | \"address\" | \"aside\" | \"b\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"button\" | \"caption\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"ins\" | \"kbd\" | \"keygen\" | \"li\" | \"mark\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"param\" | \"picture\" | \"pre\" | \"rp\" | \"rt\" | \"ruby\" | \"samp\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"video\" | \"wbr\" | \"webview\" | \"animateMotion\" | \"animateTransform\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"linearGradient\" | \"marker\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\"" + "\"symbol\" | \"object\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"source\" | \"desc\" | \"filter\" | \"text\" | \"map\" | \"head\" | React.ComponentType | \"slot\" | \"style\" | \"title\" | \"meta\" | \"pattern\" | \"summary\" | \"template\" | \"span\" | \"main\" | \"path\" | \"form\" | \"body\" | \"q\" | \"label\" | \"data\" | \"progress\" | \"legend\" | \"article\" | \"image\" | \"menu\" | \"stop\" | \"base\" | \"s\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"canvas\" | \"svg\" | \"select\" | \"output\" | \"script\" | \"time\" | \"mask\" | \"input\" | \"clipPath\" | \"section\" | \"circle\" | \"code\" | \"line\" | \"area\" | \"animate\" | \"view\" | \"var\" | \"html\" | \"a\" | \"img\" | \"audio\" | \"br\" | \"textarea\" | \"abbr\" | \"address\" | \"aside\" | \"b\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"button\" | \"caption\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"ins\" | \"kbd\" | \"keygen\" | \"li\" | \"mark\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"param\" | \"picture\" | \"pre\" | \"rp\" | \"rt\" | \"ruby\" | \"samp\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"video\" | \"wbr\" | \"webview\" | \"animateMotion\" | \"animateTransform\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"linearGradient\" | \"marker\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\"" ], "path": "packages/kbn-securitysolution-exception-list-components/src/exception_item_card/meta/index.tsx", "deprecated": false, @@ -987,7 +987,7 @@ "label": "securityLinkAnchorComponent", "description": [], "signature": [ - "\"symbol\" | \"object\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"source\" | \"desc\" | \"filter\" | \"text\" | \"map\" | \"head\" | React.ComponentType | \"slot\" | \"style\" | \"title\" | \"meta\" | \"pattern\" | \"summary\" | \"template\" | \"span\" | \"main\" | \"path\" | \"form\" | \"body\" | \"q\" | \"label\" | \"data\" | \"progress\" | \"legend\" | \"article\" | \"image\" | \"menu\" | \"stop\" | \"base\" | \"s\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"canvas\" | \"svg\" | \"select\" | \"output\" | \"script\" | \"time\" | \"mask\" | \"input\" | \"section\" | \"circle\" | \"code\" | \"line\" | \"area\" | \"animate\" | \"view\" | \"var\" | \"html\" | \"a\" | \"img\" | \"audio\" | \"br\" | \"clipPath\" | \"textarea\" | \"abbr\" | \"address\" | \"aside\" | \"b\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"button\" | \"caption\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"ins\" | \"kbd\" | \"keygen\" | \"li\" | \"mark\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"param\" | \"picture\" | \"pre\" | \"rp\" | \"rt\" | \"ruby\" | \"samp\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"video\" | \"wbr\" | \"webview\" | \"animateMotion\" | \"animateTransform\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"linearGradient\" | \"marker\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\"" + "\"symbol\" | \"object\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"source\" | \"desc\" | \"filter\" | \"text\" | \"map\" | \"head\" | React.ComponentType | \"slot\" | \"style\" | \"title\" | \"meta\" | \"pattern\" | \"summary\" | \"template\" | \"span\" | \"main\" | \"path\" | \"form\" | \"body\" | \"q\" | \"label\" | \"data\" | \"progress\" | \"legend\" | \"article\" | \"image\" | \"menu\" | \"stop\" | \"base\" | \"s\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"canvas\" | \"svg\" | \"select\" | \"output\" | \"script\" | \"time\" | \"mask\" | \"input\" | \"clipPath\" | \"section\" | \"circle\" | \"code\" | \"line\" | \"area\" | \"animate\" | \"view\" | \"var\" | \"html\" | \"a\" | \"img\" | \"audio\" | \"br\" | \"textarea\" | \"abbr\" | \"address\" | \"aside\" | \"b\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"button\" | \"caption\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"ins\" | \"kbd\" | \"keygen\" | \"li\" | \"mark\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"param\" | \"picture\" | \"pre\" | \"rp\" | \"rt\" | \"ruby\" | \"samp\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"video\" | \"wbr\" | \"webview\" | \"animateMotion\" | \"animateTransform\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"linearGradient\" | \"marker\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\"" ], "path": "packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx", "deprecated": false, @@ -1001,7 +1001,7 @@ "label": "formattedDateComponent", "description": [], "signature": [ - "\"symbol\" | \"object\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"source\" | \"desc\" | \"filter\" | \"text\" | \"map\" | \"head\" | React.ComponentType | \"slot\" | \"style\" | \"title\" | \"meta\" | \"pattern\" | \"summary\" | \"template\" | \"span\" | \"main\" | \"path\" | \"form\" | \"body\" | \"q\" | \"label\" | \"data\" | \"progress\" | \"legend\" | \"article\" | \"image\" | \"menu\" | \"stop\" | \"base\" | \"s\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"canvas\" | \"svg\" | \"select\" | \"output\" | \"script\" | \"time\" | \"mask\" | \"input\" | \"section\" | \"circle\" | \"code\" | \"line\" | \"area\" | \"animate\" | \"view\" | \"var\" | \"html\" | \"a\" | \"img\" | \"audio\" | \"br\" | \"clipPath\" | \"textarea\" | \"abbr\" | \"address\" | \"aside\" | \"b\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"button\" | \"caption\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"ins\" | \"kbd\" | \"keygen\" | \"li\" | \"mark\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"param\" | \"picture\" | \"pre\" | \"rp\" | \"rt\" | \"ruby\" | \"samp\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"video\" | \"wbr\" | \"webview\" | \"animateMotion\" | \"animateTransform\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"linearGradient\" | \"marker\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\"" + "\"symbol\" | \"object\" | \"big\" | \"link\" | \"small\" | \"sub\" | \"sup\" | \"source\" | \"desc\" | \"filter\" | \"text\" | \"map\" | \"head\" | React.ComponentType | \"slot\" | \"style\" | \"title\" | \"meta\" | \"pattern\" | \"summary\" | \"template\" | \"span\" | \"main\" | \"path\" | \"form\" | \"body\" | \"q\" | \"label\" | \"data\" | \"progress\" | \"legend\" | \"article\" | \"image\" | \"menu\" | \"stop\" | \"base\" | \"s\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"canvas\" | \"svg\" | \"select\" | \"output\" | \"script\" | \"time\" | \"mask\" | \"input\" | \"clipPath\" | \"section\" | \"circle\" | \"code\" | \"line\" | \"area\" | \"animate\" | \"view\" | \"var\" | \"html\" | \"a\" | \"img\" | \"audio\" | \"br\" | \"textarea\" | \"abbr\" | \"address\" | \"aside\" | \"b\" | \"bdi\" | \"bdo\" | \"blockquote\" | \"button\" | \"caption\" | \"cite\" | \"col\" | \"colgroup\" | \"datalist\" | \"dd\" | \"del\" | \"details\" | \"dfn\" | \"dialog\" | \"div\" | \"dl\" | \"dt\" | \"em\" | \"embed\" | \"fieldset\" | \"figcaption\" | \"figure\" | \"footer\" | \"header\" | \"hgroup\" | \"hr\" | \"i\" | \"iframe\" | \"ins\" | \"kbd\" | \"keygen\" | \"li\" | \"mark\" | \"menuitem\" | \"meter\" | \"nav\" | \"noindex\" | \"noscript\" | \"ol\" | \"optgroup\" | \"option\" | \"param\" | \"picture\" | \"pre\" | \"rp\" | \"rt\" | \"ruby\" | \"samp\" | \"strong\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"track\" | \"u\" | \"ul\" | \"video\" | \"wbr\" | \"webview\" | \"animateMotion\" | \"animateTransform\" | \"defs\" | \"ellipse\" | \"feBlend\" | \"feColorMatrix\" | \"feComponentTransfer\" | \"feComposite\" | \"feConvolveMatrix\" | \"feDiffuseLighting\" | \"feDisplacementMap\" | \"feDistantLight\" | \"feDropShadow\" | \"feFlood\" | \"feFuncA\" | \"feFuncB\" | \"feFuncG\" | \"feFuncR\" | \"feGaussianBlur\" | \"feImage\" | \"feMerge\" | \"feMergeNode\" | \"feMorphology\" | \"feOffset\" | \"fePointLight\" | \"feSpecularLighting\" | \"feSpotLight\" | \"feTile\" | \"feTurbulence\" | \"foreignObject\" | \"g\" | \"linearGradient\" | \"marker\" | \"metadata\" | \"mpath\" | \"polygon\" | \"polyline\" | \"radialGradient\" | \"rect\" | \"switch\" | \"textPath\" | \"tspan\" | \"use\"" ], "path": "packages/kbn-securitysolution-exception-list-components/src/exception_item_card/exception_item_card.tsx", "deprecated": false, diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 247825a42c7a2..bbc25b1763332 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-08-25 +date: 2023-09-04 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 ed98787b9ed57..2ebb08d1a5be5 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-08-25 +date: 2023-09-04 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 1ea5e91c8adee..4ac2b02403c09 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-08-25 +date: 2023-09-04 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 99665a0b71630..fb4b15d01a730 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-08-25 +date: 2023-09-04 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 af3796fb3f94d..95d98d0230581 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-08-25 +date: 2023-09-04 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 96f9e80a02fcb..5ee403a7fb252 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-08-25 +date: 2023-09-04 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 ebd50054b709f..ab521d578d62b 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-08-25 +date: 2023-09-04 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 5bb6a03db0fde..58e77a7bd53fd 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_securitysolution_list_constants.devdocs.json index 9da689379cb1a..c3f2279e6ccde 100644 --- a/api_docs/kbn_securitysolution_list_constants.devdocs.json +++ b/api_docs/kbn_securitysolution_list_constants.devdocs.json @@ -69,55 +69,55 @@ "references": [ { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts" + "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/blocklist_validator.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts" + "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/blocklist_validator.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/blocklist_validator.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/blocklist_validator.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts" }, { "plugin": "securitySolution", @@ -167,6 +167,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" @@ -221,19 +225,19 @@ "references": [ { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" }, { "plugin": "securitySolution", @@ -261,107 +265,107 @@ "references": [ { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx" + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/view/utils.ts" + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/view/utils.ts" + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/service_actions.ts" + "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/event_filter_validator.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/service_actions.ts" + "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/event_filter_validator.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/service_actions.ts" + "path": "x-pack/plugins/security_solution/server/lib/telemetry/tasks/security_lists.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts" + "path": "x-pack/plugins/security_solution/server/lib/telemetry/tasks/security_lists.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/view/utils.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/view/utils.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/service_actions.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/service_actions.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/service_actions.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/event_filter_validator.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/event_filter_validator.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/telemetry/tasks/security_lists.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/telemetry/tasks/security_lists.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" }, { "plugin": "securitySolution", @@ -431,6 +435,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" @@ -453,19 +461,19 @@ "references": [ { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts" }, { "plugin": "securitySolution", @@ -525,55 +533,55 @@ "references": [ { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" + "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/host_isolation_exceptions_validator.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/host_isolation_exceptions_validator.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/host_isolation_exceptions_validator.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/host_isolation_exceptions_validator.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts" }, { "plugin": "lists", @@ -639,6 +647,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" @@ -857,72 +869,72 @@ "path": "x-pack/plugins/lists/server/saved_objects/migrations.ts" }, { - "plugin": "lists", - "path": "x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" }, { - "plugin": "lists", - "path": "x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts" + "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts" + "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/api_client.ts" + "path": "x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/api_client.ts" + "path": "x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/api_client.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/lib/artifacts/lists.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/constants.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/api_client.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/api_client.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts" + "path": "x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/api_client.ts" }, { "plugin": "lists", @@ -1084,6 +1096,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts" + }, { "plugin": "@kbn/securitysolution-io-ts-list-types", "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/exception_list_schema/index.mock.ts" diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 0dccea6ab4e2f..6df5e0bfc0b59 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-08-25 +date: 2023-09-04 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 487ca96d1a054..ff905664e91dd 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-08-25 +date: 2023-09-04 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 b95aa8964dd95..88c42fad0a387 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-08-25 +date: 2023-09-04 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 cef9710263c60..5ae1f54066b70 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-08-25 +date: 2023-09-04 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 04ad4d34fd236..9f4e487548a1e 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_securitysolution_utils.devdocs.json index 54c9d41a2d799..c755b84836844 100644 --- a/api_docs/kbn_securitysolution_utils.devdocs.json +++ b/api_docs/kbn_securitysolution_utils.devdocs.json @@ -495,7 +495,7 @@ "label": "BlocklistConditionEntryField", "description": [], "signature": [ - "\"file.path\" | \"file.hash.*\" | \"file.Ext.code_signature\" | \"file.path.caseless\"" + "\"file.path\" | \"file.Ext.code_signature\" | \"file.hash.*\" | \"file.path.caseless\"" ], "path": "packages/kbn-securitysolution-utils/src/path_validations/index.ts", "deprecated": false, diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 696e1fdf09a0f..acb7bb11a3d12 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-08-25 +date: 2023-09-04 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 3ac3ed7b32bb8..7243502098eff 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-08-25 +date: 2023-09-04 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 fd4f263b4c625..a4056a67fc11b 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-08-25 +date: 2023-09-04 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_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 842bdd5278083..44567d8461ae1 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-08-25 +date: 2023-09-04 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_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index 8e9522db926e7..a36d774a828b5 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-08-25 +date: 2023-09-04 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 18abc08670050..936ee70516027 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-08-25 +date: 2023-09-04 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 29a1d0fa0d861..e82f7255d45c8 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index 267768b0ab833..713b329594e0a 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2023-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index acfcd383047eb..d163736cba8bf 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index b7d3f2d111e80..b6d4676f680e4 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2023-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 324179fa1c2d3..31dcd7e07428f 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.devdocs.json b/api_docs/kbn_shared_ux_card_no_data.devdocs.json index 796fa77d7c585..30043835cff52 100644 --- a/api_docs/kbn_shared_ux_card_no_data.devdocs.json +++ b/api_docs/kbn_shared_ux_card_no_data.devdocs.json @@ -28,7 +28,7 @@ "description": [], "signature": [ "({ href: srcHref, category, description, ...props }: ", - "NoDataCardProps", + "NoDataCardComponentProps", ") => JSX.Element" ], "path": "packages/shared-ux/card/no_data/impl/src/no_data_card.tsx", @@ -38,12 +38,12 @@ { "parentPluginId": "@kbn/shared-ux-card-no-data", "id": "def-common.NoDataCard.$1", - "type": "Object", + "type": "CompoundType", "tags": [], "label": "{ href: srcHref, category, description, ...props }", "description": [], "signature": [ - "NoDataCardProps" + "NoDataCardComponentProps" ], "path": "packages/shared-ux/card/no_data/impl/src/no_data_card.tsx", "deprecated": false, @@ -184,179 +184,9 @@ "\nProps for the `NoDataCard` sevice-connected component." ], "signature": [ - "{ prefix?: string | undefined; id?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; security?: string | undefined; children?: React.ReactNode; description?: React.ReactNode; category?: 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?: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | 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; 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; hasBorder?: boolean | undefined; paddingSize?: \"m\" | \"none\" | \"s\" | \"xs\" | \"l\" | \"xl\" | undefined; 'data-test-subj'?: string | undefined; css?: ", - "Interpolation", - "<", - "Theme", - ">; href?: string | undefined; rel?: string | undefined; target?: string | undefined; icon?: React.ReactElement<", - "EuiIconProps", - ", string | React.JSXElementConstructor> | null | undefined; image?: string | React.ReactElement> | undefined; display?: \"warning\" | \"success\" | \"subdued\" | \"primary\" | \"accent\" | \"danger\" | \"transparent\" | \"plain\" | undefined; button?: React.ReactNode; footer?: React.ReactNode; textAlign?: \"left\" | \"right\" | \"center\" | undefined; titleElement?: \"span\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | undefined; titleSize?: \"s\" | \"xs\" | undefined; betaBadgeProps?: (", - "CommonProps", - " & ", - "DisambiguateSet", - "<(", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\">), WithSpanProps> & WithSpanProps & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - " & LabelAsString) | (", - "CommonProps", - " & ", - "DisambiguateSet", - "<(", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\">), WithSpanProps> & WithSpanProps & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - " & ", - "DisambiguateSet", - "<{ title: string; tooltipContent?: React.ReactNode; }, { tooltipContent: React.ReactNode; title?: string | undefined; }> & { tooltipContent: React.ReactNode; title?: string | undefined; } & { label: React.ReactNode; }) | (", - "CommonProps", - " & ", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - " & LabelAsString) | (", - "CommonProps", - " & ", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - " & ", - "DisambiguateSet", - "<{ title: string; tooltipContent?: React.ReactNode; }, { tooltipContent: React.ReactNode; title?: string | undefined; }> & { tooltipContent: React.ReactNode; title?: string | undefined; } & { label: React.ReactNode; }) | (", - "CommonProps", - " & ", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - " & ", - "DisambiguateSet", - "<{ tooltipContent: React.ReactNode; title?: string | undefined; }, { title: string; tooltipContent?: React.ReactNode; }> & { title: string; tooltipContent?: React.ReactNode; } & { label: React.ReactNode; }) | (", - "CommonProps", - " & ", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - " & LabelAsString) | (", - "CommonProps", - " & ", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - " & ", - "DisambiguateSet", - "<{ title: string; tooltipContent?: React.ReactNode; }, { tooltipContent: React.ReactNode; title?: string | undefined; }> & { tooltipContent: React.ReactNode; title?: string | undefined; } & { label: React.ReactNode; }) | (", - "CommonProps", - " & ", - "DisambiguateSet", - " & { href: string; target?: string | undefined; rel?: string | undefined; } & Omit, \"color\" | \"onClick\" | \"href\">) | (", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\">)> & ", - "DisambiguateSet", - " & { onClick?: React.MouseEventHandler | undefined; onClickAriaLabel?: string | undefined; } & Omit, \"color\" | \"onClick\"> & { iconType?: ", - "IconType", - " | undefined; label: React.ReactNode; tooltipContent?: React.ReactNode; tooltipPosition?: ", - "ToolTipPositions", - " | undefined; anchorProps?: (", - "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", - "DisambiguateSet", - " & ", - "DisambiguateSet", - "<{ tooltipContent: React.ReactNode; title?: string | undefined; }, { title: string; tooltipContent?: React.ReactNode; }> & { title: string; tooltipContent?: React.ReactNode; } & { label: React.ReactNode; }) | undefined; selectable?: (", - "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; }) | undefined; }" + "Partial> & { button?: React.ReactNode; onClick?: React.MouseEventHandler | undefined; description?: React.ReactNode; category?: string | undefined; canAccessFleet?: boolean | undefined; }" ], "path": "packages/shared-ux/card/no_data/types/index.d.ts", "deprecated": false, diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index fdc69fffa6198..c13a9fc7925a1 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_shared_ux_card_no_data_mocks.devdocs.json index 1aa83630b7156..9283e27a593ff 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.devdocs.json +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.devdocs.json @@ -44,7 +44,7 @@ "text": "AbstractStorybookMock" }, "<", - "NoDataCardProps", + "NoDataCardComponentProps", ", ", "NoDataCardServices", ", PropArguments, ServiceArguments>" @@ -344,7 +344,7 @@ "text": "Params" }, " | undefined) => ", - "NoDataCardProps" + "NoDataCardComponentProps" ], "path": "packages/shared-ux/card/no_data/mocks/src/storybook.ts", "deprecated": false, 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 38edac7fcd3e7..1c7f02410f2e9 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-08-25 +date: 2023-09-04 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 4baf6badb8cab..71eb2e9c3ef7c 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-08-25 +date: 2023-09-04 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_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 85095ad0076aa..ad8e6e97de3cb 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-08-25 +date: 2023-09-04 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 0244808d045c9..4c7dfb2f4e1f1 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-08-25 +date: 2023-09-04 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 9bd4ae3e13c34..f4636aba01f16 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-08-25 +date: 2023-09-04 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 a1357ef0c4f6d..3f66d415c1be4 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-08-25 +date: 2023-09-04 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 be529b8499425..2f7c7b1020f93 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-08-25 +date: 2023-09-04 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 b912f11b13497..8e28b0199e9cf 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-08-25 +date: 2023-09-04 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 f034786fe99a9..9c611d85044c3 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-08-25 +date: 2023-09-04 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 99ee6e8edb6ac..b8d31a14ed26a 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-08-25 +date: 2023-09-04 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 a9ac1194e37da..da9f6ce9d5d80 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-08-25 +date: 2023-09-04 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 f75583d3cfeab..729db3aabc618 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-08-25 +date: 2023-09-04 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 5d83cb282e7ac..61f85c07db8d0 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-08-25 +date: 2023-09-04 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 50eef6dda20e3..079d165bd9e80 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_shared_ux_page_analytics_no_data.devdocs.json index 217e49d5572e4..4b6db494be35b 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.devdocs.json +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.devdocs.json @@ -66,7 +66,7 @@ "\nA pure component of an entire page that can be displayed when Kibana \"has no data\", specifically for Analytics." ], "signature": [ - "({ kibanaGuideDocLink, onDataViewCreated, allowAdHocDataView, showPlainSpinner, }: ", + "({ kibanaGuideDocLink, onDataViewCreated, allowAdHocDataView, showPlainSpinner, prependBasePath, pageFlavor, }: ", "Props", ") => JSX.Element" ], @@ -79,7 +79,7 @@ "id": "def-common.AnalyticsNoDataPage.$1", "type": "Object", "tags": [], - "label": "{\n kibanaGuideDocLink,\n onDataViewCreated,\n allowAdHocDataView,\n showPlainSpinner,\n}", + "label": "{\n kibanaGuideDocLink,\n onDataViewCreated,\n allowAdHocDataView,\n showPlainSpinner,\n prependBasePath,\n pageFlavor = 'kibana',\n}", "description": [], "signature": [ "Props" 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 907ffb0c0db44..bd00a85aafc42 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-08-25 +date: 2023-09-04 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 a990b7de48ed4..ce355c79e6cba 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-08-25 +date: 2023-09-04 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 5a5c6ea9e7d5b..3322fb8ae7795 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-08-25 +date: 2023-09-04 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 bd834c71bb041..cd7160c68a6ea 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-08-25 +date: 2023-09-04 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 04198f26241b4..aa1b4bf6bd6b1 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-08-25 +date: 2023-09-04 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 fa362e56dc50f..89e5a97aa5085 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_shared_ux_page_no_data.devdocs.json index e6f62668e8f73..9aa9a10503b95 100644 --- a/api_docs/kbn_shared_ux_page_no_data.devdocs.json +++ b/api_docs/kbn_shared_ux_page_no_data.devdocs.json @@ -172,7 +172,10 @@ "tags": [], "label": "docsLink", "description": [ - "\nRequired to set the docs link for the whole solution" + "\nRequired in \"kibana\" flavor to set the docs link for the whole solution, otherwise optional" + ], + "signature": [ + "string | undefined" ], "path": "packages/shared-ux/page/no_data/types/index.d.ts", "deprecated": false, diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 00b036fc3417a..e9ebc6c4d34dd 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-08-25 +date: 2023-09-04 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 9d522689bd0e4..db0fb2c45b33d 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-08-25 +date: 2023-09-04 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 f896707b5cd61..c03d3403bc1d9 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-08-25 +date: 2023-09-04 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 40e9b98e0be09..10db8809f145e 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-08-25 +date: 2023-09-04 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 ae1b0a48742ee..e1e19875fb3e4 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-08-25 +date: 2023-09-04 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 3d288e6785af9..a0ceb3b948671 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-08-25 +date: 2023-09-04 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 0baab963f2347..a3ef53dc7358b 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-08-25 +date: 2023-09-04 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 8f77c6d4b60e2..ce3951889ab34 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-08-25 +date: 2023-09-04 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 47b775bc5bfec..562fe2d2c6443 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-08-25 +date: 2023-09-04 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 9eff5637022bc..bc7b1792a06bc 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-08-25 +date: 2023-09-04 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 28e7f520e1f2d..9e5aa8190f0ab 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-08-25 +date: 2023-09-04 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 0011957dd65a3..3655167e60e85 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-08-25 +date: 2023-09-04 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 2ac41f986d54b..565ebfc1c67f6 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-08-25 +date: 2023-09-04 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 f3d983b94c45e..02eec6e3a39cb 100644 --- a/api_docs/kbn_slo_schema.devdocs.json +++ b/api_docs/kbn_slo_schema.devdocs.json @@ -3591,26 +3591,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "@kbn/slo-schema", - "id": "def-common.getSLODiagnosisParamsSchema", - "type": "Object", - "tags": [], - "label": "getSLODiagnosisParamsSchema", - "description": [], - "signature": [ - "TypeC", - "<{ path: ", - "TypeC", - "<{ id: ", - "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.getSLOInstancesParamsSchema", diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 38231bf84c29f..37c04eb6e8ed4 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/actionable-observability](https://github.com/orgs/elastic/team | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 133 | 0 | 130 | 0 | +| 132 | 0 | 129 | 0 | ## Common diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 2ad3d4b718e55..ebe7cb14223a6 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-08-25 +date: 2023-09-04 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 1625c3ad6c1f0..89e1d8a4e7490 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-08-25 +date: 2023-09-04 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 c9efe5915bad5..1ef8da4fd1b16 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-08-25 +date: 2023-09-04 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 d9e77ccd10f43..f14ca56b2a711 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index cadcbc87db6c4..ac91db0ff9faa 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.devdocs.json b/api_docs/kbn_test.devdocs.json index 862d934e85acc..86f6572ae1162 100644 --- a/api_docs/kbn_test.devdocs.json +++ b/api_docs/kbn_test.devdocs.json @@ -2089,6 +2089,41 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/test", + "id": "def-common.getDockerFileMountPath", + "type": "Function", + "tags": [], + "label": "getDockerFileMountPath", + "description": [ + "\nRemoves REPO_ROOT from hostPath. Keep the rest to avoid filename collisions.\nReturns the path where a file will be mounted inside the ES or ESS container.\n/root/kibana/package/foo/bar.json => /usr/share/elasticsearch/files/package/foo/bar.json" + ], + "signature": [ + "(hostPath: string) => string" + ], + "path": "packages/kbn-es/src/utils/docker.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/test", + "id": "def-common.getDockerFileMountPath.$1", + "type": "string", + "tags": [], + "label": "hostPath", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-es/src/utils/docker.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/test", "id": "def-common.getKibanaCliArg", @@ -2684,7 +2719,7 @@ "section": "def-common.EsVersion", "text": "EsVersion" }, - "; bail: boolean; dryRun: boolean; updateBaselines: boolean; updateSnapshots: boolean; logsDir: string | undefined; esFrom: \"source\" | \"snapshot\"; installDir: string | undefined; grep: string | undefined; suiteTags: { include: string[]; exclude: string[]; }; suiteFilters: { include: string[]; exclude: string[]; }; }) => Promise" + "; bail: boolean; dryRun: boolean; updateBaselines: boolean; updateSnapshots: boolean; logsDir: string | undefined; esFrom: \"source\" | \"snapshot\" | \"serverless\" | undefined; installDir: string | undefined; grep: string | undefined; suiteTags: { include: string[]; exclude: string[]; }; suiteFilters: { include: string[]; exclude: string[]; }; }) => Promise" ], "path": "packages/kbn-test/src/functional_tests/run_tests/run_tests.ts", "deprecated": false, @@ -2727,7 +2762,7 @@ "section": "def-common.EsVersion", "text": "EsVersion" }, - "; bail: boolean; dryRun: boolean; updateBaselines: boolean; updateSnapshots: boolean; logsDir: string | undefined; esFrom: \"source\" | \"snapshot\"; installDir: string | undefined; grep: string | undefined; suiteTags: { include: string[]; exclude: string[]; }; suiteFilters: { include: string[]; exclude: string[]; }; }" + "; bail: boolean; dryRun: boolean; updateBaselines: boolean; updateSnapshots: boolean; logsDir: string | undefined; esFrom: \"source\" | \"snapshot\" | \"serverless\" | undefined; installDir: string | undefined; grep: string | undefined; suiteTags: { include: string[]; exclude: string[]; }; suiteFilters: { include: string[]; exclude: string[]; }; }" ], "path": "packages/kbn-test/src/functional_tests/run_tests/run_tests.ts", "deprecated": false, @@ -2819,7 +2854,7 @@ "section": "def-common.ToolingLog", "text": "ToolingLog" }, - ", options: { config: string; esFrom: \"source\" | \"snapshot\" | undefined; esVersion: ", + ", options: { config: string; esFrom: \"source\" | \"snapshot\" | \"serverless\" | undefined; esVersion: ", { "pluginId": "@kbn/test", "scope": "common", @@ -2862,7 +2897,7 @@ "label": "options", "description": [], "signature": [ - "{ config: string; esFrom: \"source\" | \"snapshot\" | undefined; esVersion: ", + "{ config: string; esFrom: \"source\" | \"snapshot\" | \"serverless\" | undefined; esVersion: ", { "pluginId": "@kbn/test", "scope": "common", @@ -3254,6 +3289,38 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "@kbn/test", + "id": "def-common.CreateTestEsClusterOptions.serverless", + "type": "CompoundType", + "tags": [], + "label": "serverless", + "description": [ + "\nIs this a serverless project" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-test/src/es/test_es_cluster.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/test", + "id": "def-common.CreateTestEsClusterOptions.files", + "type": "Array", + "tags": [], + "label": "files", + "description": [ + "\nFiles to mount inside ES containers" + ], + "signature": [ + "string[] | undefined" + ], + "path": "packages/kbn-test/src/es/test_es_cluster.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -5238,6 +5305,42 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/test", + "id": "def-common.kibanaTestSuperuserServerless", + "type": "Object", + "tags": [], + "label": "kibanaTestSuperuserServerless", + "description": [], + "path": "packages/kbn-test/src/kbn/users.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/test", + "id": "def-common.kibanaTestSuperuserServerless.username", + "type": "string", + "tags": [], + "label": "username", + "description": [], + "path": "packages/kbn-test/src/kbn/users.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/test", + "id": "def-common.kibanaTestSuperuserServerless.password", + "type": "string", + "tags": [], + "label": "password", + "description": [], + "path": "packages/kbn-test/src/kbn/users.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/test", "id": "def-common.kibanaTestUser", diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 3fffa3f5efd6e..7264212956b32 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kiban | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 282 | 4 | 238 | 12 | +| 289 | 4 | 242 | 12 | ## Common diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index a015075da2188..1bf2c9e9b53f7 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-08-25 +date: 2023-09-04 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 4b77bc03c59d9..5d509393bb515 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_text_based_editor.devdocs.json index 1eb1abc6f8275..e0ba49c3e1b0e 100644 --- a/api_docs/kbn_text_based_editor.devdocs.json +++ b/api_docs/kbn_text_based_editor.devdocs.json @@ -203,6 +203,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/text-based-editor", + "id": "def-public.TextBasedLanguagesEditorProps.warning", + "type": "string", + "tags": [], + "label": "warning", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-text-based-editor/src/text_based_languages_editor.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/text-based-editor", "id": "def-public.TextBasedLanguagesEditorProps.isDisabled", @@ -244,6 +258,20 @@ "path": "packages/kbn-text-based-editor/src/text_based_languages_editor.tsx", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/text-based-editor", + "id": "def-public.TextBasedLanguagesEditorProps.hideMinimizeButton", + "type": "CompoundType", + "tags": [], + "label": "hideMinimizeButton", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-text-based-editor/src/text_based_languages_editor.tsx", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index 822ebabb345e4..ccd497d35149e 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.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 | |-------------------|-----------|------------------------|-----------------| -| 15 | 0 | 14 | 0 | +| 17 | 0 | 16 | 0 | ## Client diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 21662dad2d915..28b888a532cab 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-08-25 +date: 2023-09-04 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 d6eb0208079d2..e8906be6f4126 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-08-25 +date: 2023-09-04 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 f6f8bad296d7a..e90938685a9b3 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-08-25 +date: 2023-09-04 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 0ccb887a3cac3..def5e7fddeff8 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-08-25 +date: 2023-09-04 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 10ba047d0e2a0..808f95cb57177 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-08-25 +date: 2023-09-04 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 48dccff27b119..71fab2a4a30ca 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_unified_data_table.devdocs.json new file mode 100644 index 0000000000000..ae7cb737b9638 --- /dev/null +++ b/api_docs/kbn_unified_data_table.devdocs.json @@ -0,0 +1,1584 @@ +{ + "id": "@kbn/unified-data-table", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.getDisplayedColumns", + "type": "Function", + "tags": [], + "label": "getDisplayedColumns", + "description": [ + "\nFunction to provide fallback when\n1) no columns are given\n2) Just one column is given, which is the configured timefields" + ], + "signature": [ + "(stateColumns: string[], dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ") => string[]" + ], + "path": "packages/kbn-unified-data-table/src/utils/columns.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.getDisplayedColumns.$1", + "type": "Array", + "tags": [], + "label": "stateColumns", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/kbn-unified-data-table/src/utils/columns.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.getDisplayedColumns.$2", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "packages/kbn-unified-data-table/src/utils/columns.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.getRowsPerPageOptions", + "type": "Function", + "tags": [], + "label": "getRowsPerPageOptions", + "description": [], + "signature": [ + "(currentRowsPerPage?: number | undefined) => number[]" + ], + "path": "packages/kbn-unified-data-table/src/utils/rows_per_page.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.getRowsPerPageOptions.$1", + "type": "number", + "tags": [], + "label": "currentRowsPerPage", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-unified-data-table/src/utils/rows_per_page.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.JSONCodeEditorCommonMemoized", + "type": "Function", + "tags": [], + "label": "JSONCodeEditorCommonMemoized", + "description": [], + "signature": [ + "React.NamedExoticComponent & { readonly type: (props: JsonCodeEditorCommonProps) => JSX.Element; }" + ], + "path": "packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor_common.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.JSONCodeEditorCommonMemoized.$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/unified-data-table", + "id": "def-common.popularizeField", + "type": "Function", + "tags": [], + "label": "popularizeField", + "description": [], + "signature": [ + "(dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ", fieldName: string, DataViewsService: ", + { + "pluginId": "dataViews", + "scope": "public", + "docId": "kibDataViewsPluginApi", + "section": "def-public.DataViewsServicePublic", + "text": "DataViewsServicePublic" + }, + ", capabilities: ", + { + "pluginId": "@kbn/core-capabilities-common", + "scope": "common", + "docId": "kibKbnCoreCapabilitiesCommonPluginApi", + "section": "def-common.Capabilities", + "text": "Capabilities" + }, + ") => Promise" + ], + "path": "packages/kbn-unified-data-table/src/utils/popularize_field.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.popularizeField.$1", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "packages/kbn-unified-data-table/src/utils/popularize_field.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.popularizeField.$2", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-unified-data-table/src/utils/popularize_field.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.popularizeField.$3", + "type": "Object", + "tags": [], + "label": "DataViewsService", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "public", + "docId": "kibDataViewsPluginApi", + "section": "def-public.DataViewsServicePublic", + "text": "DataViewsServicePublic" + } + ], + "path": "packages/kbn-unified-data-table/src/utils/popularize_field.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.popularizeField.$4", + "type": "Object", + "tags": [], + "label": "capabilities", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-capabilities-common", + "scope": "common", + "docId": "kibKbnCoreCapabilitiesCommonPluginApi", + "section": "def-common.Capabilities", + "text": "Capabilities" + } + ], + "path": "packages/kbn-unified-data-table/src/utils/popularize_field.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTable", + "type": "Function", + "tags": [], + "label": "UnifiedDataTable", + "description": [], + "signature": [ + "({ ariaLabelledBy, columns, controlColumnIds, dataView, loadingState, onFilter, onResize, onSetColumns, onSort, rows, sampleSize, searchDescription, searchTitle, settings, showTimeCol, showFullScreenButton, sort, useNewFieldsApi, isSortEnabled, isPaginationEnabled, cellActionsTriggerId, className, rowHeightState, onUpdateRowHeight, isPlainRecord, rowsPerPageState, onUpdateRowsPerPage, onFieldEdited, services, renderCustomGridBody, trailingControlColumns, totalHits, onFetchMoreRecords, renderDocumentView, setExpandedDoc, expandedDoc, configRowHeight, showMultiFields, maxDocFieldsDisplayed, externalControlColumns, externalAdditionalControls, rowsPerPageOptions, visibleCellActions, externalCustomRenderers, consumer, componentsTourSteps, }: ", + { + "pluginId": "@kbn/unified-data-table", + "scope": "common", + "docId": "kibKbnUnifiedDataTablePluginApi", + "section": "def-common.UnifiedDataTableProps", + "text": "UnifiedDataTableProps" + }, + ") => JSX.Element" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTable.$1", + "type": "Object", + "tags": [], + "label": "{\n ariaLabelledBy,\n columns,\n controlColumnIds = CONTROL_COLUMN_IDS_DEFAULT,\n dataView,\n loadingState,\n onFilter,\n onResize,\n onSetColumns,\n onSort,\n rows,\n sampleSize,\n searchDescription,\n searchTitle,\n settings,\n showTimeCol,\n showFullScreenButton = true,\n sort,\n useNewFieldsApi,\n isSortEnabled = true,\n isPaginationEnabled = true,\n cellActionsTriggerId,\n className,\n rowHeightState,\n onUpdateRowHeight,\n isPlainRecord = false,\n rowsPerPageState,\n onUpdateRowsPerPage,\n onFieldEdited,\n services,\n renderCustomGridBody,\n trailingControlColumns,\n totalHits,\n onFetchMoreRecords,\n renderDocumentView,\n setExpandedDoc,\n expandedDoc,\n configRowHeight,\n showMultiFields = true,\n maxDocFieldsDisplayed = 50,\n externalControlColumns,\n externalAdditionalControls,\n rowsPerPageOptions,\n visibleCellActions,\n externalCustomRenderers,\n consumer = 'discover',\n componentsTourSteps,\n}", + "description": [], + "signature": [ + { + "pluginId": "@kbn/unified-data-table", + "scope": "common", + "docId": "kibKbnUnifiedDataTablePluginApi", + "section": "def-common.UnifiedDataTableProps", + "text": "UnifiedDataTableProps" + } + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.useColumns", + "type": "Function", + "tags": [], + "label": "useColumns", + "description": [], + "signature": [ + "({ capabilities, dataView, dataViews, setAppState, useNewFieldsApi, columns, sort, defaultOrder, }: UseColumnsProps) => { columns: string[]; onAddColumn: (columnName: string) => void; onRemoveColumn: (columnName: string) => void; onMoveColumn: (columnName: string, newIndex: number) => void; onSetColumns: (nextColumns: string[], hideTimeColumn: boolean) => void; }" + ], + "path": "packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.useColumns.$1", + "type": "Object", + "tags": [], + "label": "{\n capabilities,\n dataView,\n dataViews,\n setAppState,\n useNewFieldsApi,\n columns,\n sort,\n defaultOrder = 'desc',\n}", + "description": [], + "signature": [ + "UseColumnsProps" + ], + "path": "packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps", + "type": "Interface", + "tags": [], + "label": "UnifiedDataTableProps", + "description": [], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.ariaLabelledBy", + "type": "string", + "tags": [], + "label": "ariaLabelledBy", + "description": [ + "\nDetermines which element labels the grid for ARIA" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.className", + "type": "string", + "tags": [], + "label": "className", + "description": [ + "\nOptional class name to apply" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.columns", + "type": "Array", + "tags": [], + "label": "columns", + "description": [ + "\nDetermines ids of the columns which are displayed" + ], + "signature": [ + "string[]" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.expandedDoc", + "type": "Object", + "tags": [], + "label": "expandedDoc", + "description": [ + "\nIf set, the given document is displayed in a flyout" + ], + "signature": [ + "DataTableRecord", + " | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.dataView", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [ + "\nThe used data view" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.loadingState", + "type": "Enum", + "tags": [], + "label": "loadingState", + "description": [ + "\nDetermines if data is currently loaded" + ], + "signature": [ + { + "pluginId": "@kbn/unified-data-table", + "scope": "common", + "docId": "kibKbnUnifiedDataTablePluginApi", + "section": "def-common.DataLoadingState", + "text": "DataLoadingState" + } + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onFilter", + "type": "Function", + "tags": [], + "label": "onFilter", + "description": [ + "\nFunction to add a filter in the grid cell or document flyout" + ], + "signature": [ + "(mapping: string | ", + "FieldMapping", + " | undefined, value: unknown, mode: \"+\" | \"-\") => void" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onFilter.$1", + "type": "CompoundType", + "tags": [], + "label": "mapping", + "description": [], + "signature": [ + "string | ", + "FieldMapping", + " | undefined" + ], + "path": "packages/kbn-unified-doc-viewer/src/services/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onFilter.$2", + "type": "Unknown", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "unknown" + ], + "path": "packages/kbn-unified-doc-viewer/src/services/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onFilter.$3", + "type": "CompoundType", + "tags": [], + "label": "mode", + "description": [], + "signature": [ + "\"+\" | \"-\"" + ], + "path": "packages/kbn-unified-doc-viewer/src/services/types.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onResize", + "type": "Function", + "tags": [], + "label": "onResize", + "description": [ + "\nFunction triggered when a column is resized by the user" + ], + "signature": [ + "((colSettings: { columnId: string; width: number; }) => void) | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onResize.$1", + "type": "Object", + "tags": [], + "label": "colSettings", + "description": [], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onResize.$1.columnId", + "type": "string", + "tags": [], + "label": "columnId", + "description": [], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onResize.$1.width", + "type": "number", + "tags": [], + "label": "width", + "description": [], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onSetColumns", + "type": "Function", + "tags": [], + "label": "onSetColumns", + "description": [ + "\nFunction to set all columns" + ], + "signature": [ + "(columns: string[], hideTimeColumn: boolean) => void" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onSetColumns.$1", + "type": "Array", + "tags": [], + "label": "columns", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onSetColumns.$2", + "type": "boolean", + "tags": [], + "label": "hideTimeColumn", + "description": [], + "signature": [ + "boolean" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onSort", + "type": "Function", + "tags": [], + "label": "onSort", + "description": [ + "\nfunction to change sorting of the documents, skipped when isSortEnabled is set to false" + ], + "signature": [ + "((sort: string[][]) => void) | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onSort.$1", + "type": "Array", + "tags": [], + "label": "sort", + "description": [], + "signature": [ + "string[][]" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.rows", + "type": "Array", + "tags": [], + "label": "rows", + "description": [ + "\nArray of documents provided by Elasticsearch" + ], + "signature": [ + "DataTableRecord", + "[] | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.sampleSize", + "type": "number", + "tags": [], + "label": "sampleSize", + "description": [ + "\nThe max size of the documents returned by Elasticsearch" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.setExpandedDoc", + "type": "Function", + "tags": [], + "label": "setExpandedDoc", + "description": [ + "\nFunction to set the expanded document, which is displayed in a flyout" + ], + "signature": [ + "((doc?: ", + "DataTableRecord", + " | undefined) => void) | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.setExpandedDoc.$1", + "type": "Object", + "tags": [], + "label": "doc", + "description": [], + "signature": [ + "DataTableRecord", + " | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.settings", + "type": "Object", + "tags": [], + "label": "settings", + "description": [ + "\nGrid display settings persisted in Elasticsearch (e.g. column width)" + ], + "signature": [ + { + "pluginId": "@kbn/unified-data-table", + "scope": "common", + "docId": "kibKbnUnifiedDataTablePluginApi", + "section": "def-common.UnifiedDataTableSettings", + "text": "UnifiedDataTableSettings" + }, + " | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.searchDescription", + "type": "string", + "tags": [], + "label": "searchDescription", + "description": [ + "\nSearch description" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.searchTitle", + "type": "string", + "tags": [], + "label": "searchTitle", + "description": [ + "\nSearch title" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.showTimeCol", + "type": "boolean", + "tags": [], + "label": "showTimeCol", + "description": [ + "\nDetermines whether the time columns should be displayed (legacy settings)" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.showFullScreenButton", + "type": "CompoundType", + "tags": [], + "label": "showFullScreenButton", + "description": [ + "\nDetermines whether the full screen button should be displayed" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.isSortEnabled", + "type": "CompoundType", + "tags": [], + "label": "isSortEnabled", + "description": [ + "\nManage user sorting control" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.sort", + "type": "Array", + "tags": [], + "label": "sort", + "description": [ + "\nCurrent sort setting" + ], + "signature": [ + "SortOrder", + "[]" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.useNewFieldsApi", + "type": "boolean", + "tags": [], + "label": "useNewFieldsApi", + "description": [ + "\nHow the data is fetched" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.isPaginationEnabled", + "type": "CompoundType", + "tags": [], + "label": "isPaginationEnabled", + "description": [ + "\nManage pagination control" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.controlColumnIds", + "type": "Array", + "tags": [], + "label": "controlColumnIds", + "description": [ + "\nList of used control columns (available: 'openDetails', 'select')" + ], + "signature": [ + "string[] | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.rowHeightState", + "type": "number", + "tags": [], + "label": "rowHeightState", + "description": [ + "\nRow height from state" + ], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onUpdateRowHeight", + "type": "Function", + "tags": [], + "label": "onUpdateRowHeight", + "description": [ + "\nUpdate row height state" + ], + "signature": [ + "((rowHeight: number) => void) | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onUpdateRowHeight.$1", + "type": "number", + "tags": [], + "label": "rowHeight", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.isPlainRecord", + "type": "CompoundType", + "tags": [], + "label": "isPlainRecord", + "description": [ + "\nIs text base lang mode enabled" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.rowsPerPageState", + "type": "number", + "tags": [], + "label": "rowsPerPageState", + "description": [ + "\nCurrent state value for rowsPerPage" + ], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onUpdateRowsPerPage", + "type": "Function", + "tags": [], + "label": "onUpdateRowsPerPage", + "description": [ + "\nUpdate rows per page state" + ], + "signature": [ + "((rowsPerPage: number) => void) | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onUpdateRowsPerPage.$1", + "type": "number", + "tags": [], + "label": "rowsPerPage", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onFieldEdited", + "type": "Function", + "tags": [], + "label": "onFieldEdited", + "description": [ + "\nCallback to execute on edit runtime field" + ], + "signature": [ + "(() => void) | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.cellActionsTriggerId", + "type": "string", + "tags": [], + "label": "cellActionsTriggerId", + "description": [ + "\nOptional triggerId to retrieve the column cell actions that will override the default ones" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.services", + "type": "Object", + "tags": [], + "label": "services", + "description": [ + "\nService dependencies" + ], + "signature": [ + "{ theme: ", + { + "pluginId": "@kbn/react-kibana-context-common", + "scope": "common", + "docId": "kibKbnReactKibanaContextCommonPluginApi", + "section": "def-common.ThemeServiceStart", + "text": "ThemeServiceStart" + }, + "; fieldFormats: ", + { + "pluginId": "fieldFormats", + "scope": "public", + "docId": "kibFieldFormatsPluginApi", + "section": "def-public.FieldFormatsStart", + "text": "FieldFormatsStart" + }, + "; uiSettings: ", + { + "pluginId": "@kbn/core-ui-settings-browser", + "scope": "common", + "docId": "kibKbnCoreUiSettingsBrowserPluginApi", + "section": "def-common.IUiSettingsClient", + "text": "IUiSettingsClient" + }, + "; dataViewFieldEditor: ", + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.PluginStart", + "text": "PluginStart" + }, + "; toastNotifications: ", + { + "pluginId": "@kbn/core-notifications-browser", + "scope": "common", + "docId": "kibKbnCoreNotificationsBrowserPluginApi", + "section": "def-common.IToasts", + "text": "IToasts" + }, + "; storage: ", + { + "pluginId": "kibanaUtils", + "scope": "public", + "docId": "kibKibanaUtilsPluginApi", + "section": "def-public.Storage", + "text": "Storage" + }, + "; data: ", + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataPluginApi", + "section": "def-public.DataPublicPluginStart", + "text": "DataPublicPluginStart" + }, + "; }" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.renderDocumentView", + "type": "Function", + "tags": [], + "label": "renderDocumentView", + "description": [ + "\nCallback to render DocumentView when the document is expanded" + ], + "signature": [ + "((hit: ", + "DataTableRecord", + ", displayedRows: ", + "DataTableRecord", + "[], displayedColumns: string[]) => JSX.Element | undefined) | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.renderDocumentView.$1", + "type": "Object", + "tags": [], + "label": "hit", + "description": [], + "signature": [ + "DataTableRecord" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.renderDocumentView.$2", + "type": "Array", + "tags": [], + "label": "displayedRows", + "description": [], + "signature": [ + "DataTableRecord", + "[]" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.renderDocumentView.$3", + "type": "Array", + "tags": [], + "label": "displayedColumns", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.configRowHeight", + "type": "number", + "tags": [], + "label": "configRowHeight", + "description": [ + "\nOptional value for providing configuration setting for UnifiedDataTable rows height" + ], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.showMultiFields", + "type": "CompoundType", + "tags": [], + "label": "showMultiFields", + "description": [ + "\nOptional value for providing configuration setting for enabling to display the complex fields in the table. Default is true." + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.maxDocFieldsDisplayed", + "type": "number", + "tags": [], + "label": "maxDocFieldsDisplayed", + "description": [ + "\nOptional value for providing configuration setting for maximum number of document fields to display in the table. Default is 50." + ], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.externalControlColumns", + "type": "Array", + "tags": [], + "label": "externalControlColumns", + "description": [ + "\nOptional value for providing EuiDataGridControlColumn list of the additional leading control columns. UnifiedDataTable includes two control columns: Open Details and Select." + ], + "signature": [ + "EuiDataGridControlColumn", + "[] | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.totalHits", + "type": "number", + "tags": [], + "label": "totalHits", + "description": [ + "\nNumber total hits from ES" + ], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.onFetchMoreRecords", + "type": "Function", + "tags": [], + "label": "onFetchMoreRecords", + "description": [ + "\nTo fetch more" + ], + "signature": [ + "(() => void) | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.externalAdditionalControls", + "type": "CompoundType", + "tags": [], + "label": "externalAdditionalControls", + "description": [ + "\nOptional value for providing the additional controls available in the UnifiedDataTable toolbar to manage it's records or state. UnifiedDataTable includes Columns, Sorting and Bulk Actions." + ], + "signature": [ + "boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | null | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.rowsPerPageOptions", + "type": "Array", + "tags": [], + "label": "rowsPerPageOptions", + "description": [ + "\nOptional list of number type values to set custom UnifiedDataTable paging options to display the records per page." + ], + "signature": [ + "number[] | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.renderCustomGridBody", + "type": "Function", + "tags": [], + "label": "renderCustomGridBody", + "description": [ + "\nAn optional function called to completely customize and control the rendering of\nEuiDataGrid's body and cell placement. This can be used to, e.g. remove EuiDataGrid's\nvirtualization library, or roll your own.\n\nThis component is **only** meant as an escape hatch for extremely custom use cases.\n\nBehind the scenes, this function is treated as a React component,\nallowing hooks, context, and other React concepts to be used.\nIt receives #EuiDataGridCustomBodyProps as its only argument." + ], + "signature": [ + "((args: ", + "EuiDataGridCustomBodyProps", + ") => React.ReactNode) | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.renderCustomGridBody.$1", + "type": "Object", + "tags": [], + "label": "args", + "description": [], + "signature": [ + "EuiDataGridCustomBodyProps" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.trailingControlColumns", + "type": "Array", + "tags": [], + "label": "trailingControlColumns", + "description": [ + "\nAn optional list of the EuiDataGridControlColumn type for setting trailing control columns standard for EuiDataGrid." + ], + "signature": [ + "EuiDataGridControlColumn", + "[] | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.visibleCellActions", + "type": "number", + "tags": [], + "label": "visibleCellActions", + "description": [ + "\nAn optional value for a custom number of the visible cell actions in the table. By default is up to 3." + ], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.externalCustomRenderers", + "type": "Object", + "tags": [], + "label": "externalCustomRenderers", + "description": [ + "\nAn optional settings for a specified fields rendering like links. Applied only for the listed fields rendering." + ], + "signature": [ + "Record React.ReactNode> | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.consumer", + "type": "string", + "tags": [], + "label": "consumer", + "description": [ + "\nName of the UnifiedDataTable consumer component or application" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableProps.componentsTourSteps", + "type": "Object", + "tags": [], + "label": "componentsTourSteps", + "description": [ + "\nOptional key/value pairs to set guided onboarding steps ids for a data table components included to guided tour." + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableSettings", + "type": "Interface", + "tags": [], + "label": "UnifiedDataTableSettings", + "description": [ + "\nUser configurable state of data grid, persisted in saved search" + ], + "path": "packages/kbn-unified-data-table/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableSettings.columns", + "type": "Object", + "tags": [], + "label": "columns", + "description": [], + "signature": [ + "Record | undefined" + ], + "path": "packages/kbn-unified-data-table/src/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableSettingsColumn", + "type": "Interface", + "tags": [], + "label": "UnifiedDataTableSettingsColumn", + "description": [], + "path": "packages/kbn-unified-data-table/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.UnifiedDataTableSettingsColumn.width", + "type": "number", + "tags": [], + "label": "width", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-unified-data-table/src/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.DataLoadingState", + "type": "Enum", + "tags": [], + "label": "DataLoadingState", + "description": [], + "path": "packages/kbn-unified-data-table/src/components/data_table.tsx", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.ValueToStringConverter", + "type": "Type", + "tags": [], + "label": "ValueToStringConverter", + "description": [], + "signature": [ + "(rowIndex: number, columnId: string, options?: { compatibleWithCSV?: boolean | undefined; } | undefined) => { formattedString: string; withFormula: boolean; }" + ], + "path": "packages/kbn-unified-data-table/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.ValueToStringConverter.$1", + "type": "number", + "tags": [], + "label": "rowIndex", + "description": [], + "path": "packages/kbn-unified-data-table/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.ValueToStringConverter.$2", + "type": "string", + "tags": [], + "label": "columnId", + "description": [], + "path": "packages/kbn-unified-data-table/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/unified-data-table", + "id": "def-common.ValueToStringConverter.$3", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "{ compatibleWithCSV?: boolean | undefined; } | undefined" + ], + "path": "packages/kbn-unified-data-table/src/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx new file mode 100644 index 0000000000000..2e0d365f08b42 --- /dev/null +++ b/api_docs/kbn_unified_data_table.mdx @@ -0,0 +1,39 @@ +--- +#### +#### 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: kibKbnUnifiedDataTablePluginApi +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-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] +--- +import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; + +Contains functionality for the unified data table which can be integrated into apps + +Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 88 | 0 | 39 | 1 | + +## Common + +### Functions + + +### Interfaces + + +### Enums + + +### Consts, variables and types + + diff --git a/api_docs/kbn_unified_doc_viewer.devdocs.json b/api_docs/kbn_unified_doc_viewer.devdocs.json new file mode 100644 index 0000000000000..da1c2b438bd70 --- /dev/null +++ b/api_docs/kbn_unified_doc_viewer.devdocs.json @@ -0,0 +1,204 @@ +{ + "id": "@kbn/unified-doc-viewer", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [ + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.DocViewsRegistry", + "type": "Class", + "tags": [], + "label": "DocViewsRegistry", + "description": [], + "path": "packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.DocViewsRegistry.addDocView", + "type": "Function", + "tags": [], + "label": "addDocView", + "description": [ + "\nExtends and adds the given doc view to the registry array" + ], + "signature": [ + "(docViewRaw: ", + "DocViewInput", + " | ", + "DocViewInputFn", + ") => void" + ], + "path": "packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.DocViewsRegistry.addDocView.$1", + "type": "CompoundType", + "tags": [], + "label": "docViewRaw", + "description": [], + "signature": [ + "DocViewInput", + " | ", + "DocViewInputFn" + ], + "path": "packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.DocViewsRegistry.getDocViewsSorted", + "type": "Function", + "tags": [], + "label": "getDocViewsSorted", + "description": [ + "\nReturns a sorted array of doc_views for rendering tabs" + ], + "signature": [ + "(hit: ", + "DataTableRecord", + ") => ", + "DocView", + "[]" + ], + "path": "packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.DocViewsRegistry.getDocViewsSorted.$1", + "type": "Object", + "tags": [], + "label": "hit", + "description": [], + "signature": [ + "DataTableRecord" + ], + "path": "packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.DocViewer", + "type": "Function", + "tags": [], + "label": "DocViewer", + "description": [ + "\nRendering tabs with different views of 1 Elasticsearch hit in Discover.\nThe tabs are provided by the `docs_views` registry.\nA view can contain a React `component`, or any JS framework by using\na `render` function." + ], + "signature": [ + "({ docViews, ...renderProps }: ", + "DocViewerProps", + ") => JSX.Element | null" + ], + "path": "packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.DocViewer.$1", + "type": "Object", + "tags": [], + "label": "{ docViews, ...renderProps }", + "description": [], + "signature": [ + "DocViewerProps" + ], + "path": "packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.FieldName", + "type": "Function", + "tags": [], + "label": "FieldName", + "description": [], + "signature": [ + "({\n fieldName,\n fieldMapping,\n fieldType,\n fieldIconProps,\n scripted = false,\n highlight = '',\n}: Props) => JSX.Element" + ], + "path": "packages/kbn-unified-doc-viewer/src/components/field_name/field_name.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.FieldName.$1", + "type": "Object", + "tags": [], + "label": "{\n fieldName,\n fieldMapping,\n fieldType,\n fieldIconProps,\n scripted = false,\n highlight = '',\n}", + "description": [], + "signature": [ + "Props" + ], + "path": "packages/kbn-unified-doc-viewer/src/components/field_name/field_name.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [ + { + "parentPluginId": "@kbn/unified-doc-viewer", + "id": "def-common.ElasticRequestState", + "type": "Enum", + "tags": [], + "label": "ElasticRequestState", + "description": [], + "path": "packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx new file mode 100644 index 0000000000000..5ebcc91264602 --- /dev/null +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnUnifiedDocViewerPluginApi +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-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] +--- +import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; + + + +Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 10 | 0 | 7 | 6 | + +## Common + +### Functions + + +### Classes + + +### Enums + + diff --git a/api_docs/kbn_unified_field_list.devdocs.json b/api_docs/kbn_unified_field_list.devdocs.json index 88f3b347e3f0b..dddaeb04aa725 100644 --- a/api_docs/kbn_unified_field_list.devdocs.json +++ b/api_docs/kbn_unified_field_list.devdocs.json @@ -796,41 +796,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/unified-field-list", - "id": "def-common.getFieldTypeName", - "type": "Function", - "tags": [], - "label": "getFieldTypeName", - "description": [ - "\nReturns a user-friendly name of a field type" - ], - "signature": [ - "(type: string | undefined) => string" - ], - "path": "packages/kbn-unified-field-list/src/utils/field_types/get_field_type_name.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/unified-field-list", - "id": "def-common.getFieldTypeName.$1", - "type": "string", - "tags": [], - "label": "type", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-unified-field-list/src/utils/field_types/get_field_type_name.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/unified-field-list", "id": "def-common.getSearchMode", @@ -5518,20 +5483,6 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/unified-field-list", - "id": "def-common.KNOWN_FIELD_TYPES", - "type": "Enum", - "tags": [], - "label": "KNOWN_FIELD_TYPES", - "description": [ - "\nField types for which name and description are defined" - ], - "path": "packages/kbn-unified-field-list/src/utils/field_types/field_types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false } ], "misc": [ @@ -5691,21 +5642,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "@kbn/unified-field-list", - "id": "def-common.FieldTypeKnown", - "type": "Type", - "tags": [], - "label": "FieldTypeKnown", - "description": [], - "signature": [ - "string" - ], - "path": "packages/kbn-unified-field-list/src/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "@kbn/unified-field-list", "id": "def-common.GetCustomFieldType", diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 5212df39a9773..099031ba5a3da 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.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 | |-------------------|-----------|------------------------|-----------------| -| 306 | 0 | 277 | 9 | +| 302 | 0 | 275 | 9 | ## Common diff --git a/api_docs/kbn_url_state.mdx b/api_docs/kbn_url_state.mdx index 7b6b220c13e58..aab54258fdf86 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-08-25 +date: 2023-09-04 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 4658de4d31f75..a2f536a06bfcc 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/use-tracked-promise'] --- import kbnUseTrackedPromiseObj from './kbn_use_tracked_promise.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 729eb82a5cf58..9b243681feaf4 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-08-25 +date: 2023-09-04 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.devdocs.json b/api_docs/kbn_utility_types.devdocs.json index 821e2d7a40523..6d177a2aa2cf2 100644 --- a/api_docs/kbn_utility_types.devdocs.json +++ b/api_docs/kbn_utility_types.devdocs.json @@ -627,6 +627,61 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/utility-types", + "id": "def-common.RecursivePartial", + "type": "Type", + "tags": [], + "label": "RecursivePartial", + "description": [], + "signature": [ + "{ [P in keyof T]?: (T[P] extends NonAny[] ? T[P] : T[P] extends readonly NonAny[] ? T[P] : T[P] extends (infer U)[] ? ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "[] : T[P] extends readonly (infer U)[] ? readonly ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "[] : T[P] extends Set ? Set<", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + "> : T[P] extends Map ? Map> : T[P] extends NonAny ? T[P] : ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.RecursivePartial", + "text": "RecursivePartial" + }, + ") | undefined; }" + ], + "path": "packages/kbn-utility-types/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/utility-types", "id": "def-common.RecursiveReadonly", diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 94fec28c70bec..ad1d200cbef90 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 36 | 0 | 15 | 1 | +| 37 | 0 | 16 | 1 | ## Common diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 82210a5ba466e..29e8231029c8b 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-08-25 +date: 2023-09-04 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 eedd79ee09f65..0525b690734d2 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 083f580e83293..b7f18f9d9ab45 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 40a70a9e553bc..dff93325d9d1d 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 243222eb30042..c9de87d3aff23 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-08-25 +date: 2023-09-04 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 81e2b6adc1677..3133e29cbacf4 100644 --- a/api_docs/kibana_react.devdocs.json +++ b/api_docs/kibana_react.devdocs.json @@ -777,64 +777,152 @@ "path": "x-pack/plugins/spaces/public/space_selector/space_selector.tsx" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/save_modal/show_saved_object_save_modal.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/save_modal/show_saved_object_save_modal.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/save_modal/show_saved_object_save_modal.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/login/login_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/login/login_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/login/login_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx" + "plugin": "security", + "path": "x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/management/users/users_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/management/users/users_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/management/users/users_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/management/roles/roles_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/management/roles/roles_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/management/roles/roles_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/nav_control/nav_control_service.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/nav_control/nav_control_service.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/nav_control/nav_control_service.tsx" + }, + { + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/save_modal/show_saved_object_save_modal.tsx" + }, + { + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/save_modal/show_saved_object_save_modal.tsx" + }, + { + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/save_modal/show_saved_object_save_modal.tsx" + }, + { + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/public/shared_imports.ts" + }, + { + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/public/application/index.tsx" + }, + { + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/public/application/index.tsx" + }, + { + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/public/application/index.tsx" }, { "plugin": "serverless", @@ -908,6 +996,54 @@ "plugin": "visualizations", "path": "src/plugins/visualizations/public/visualize_app/index.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx" + }, { "plugin": "dashboard", "path": "src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx" @@ -1020,173 +1156,53 @@ "plugin": "lens", "path": "x-pack/plugins/lens/public/app_plugin/settings_menu.tsx" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/settings_menu.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/settings_menu.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/mounter.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/mounter.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/mounter.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/access_agreement/access_agreement_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/logged_out/logged_out_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/login/login_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/login/login_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/login/login_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_page.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/api_keys/api_keys_management_app.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/users/users_management_app.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/users/users_management_app.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/users/users_management_app.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/roles/roles_management_app.tsx" + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/settings_menu.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/roles/roles_management_app.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/settings_menu.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/roles/roles_management_app.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/mounter.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/mounter.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/mounter.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/nav_control/nav_control_service.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/nav_control/nav_control_service.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" }, { - "plugin": "security", - "path": "x-pack/plugins/security/public/nav_control/nav_control_service.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx" }, { "plugin": "alerting", @@ -1236,66 +1252,6 @@ "plugin": "cases", "path": "x-pack/plugins/cases/public/application.tsx" }, - { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx" - }, - { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx" - }, - { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx" - }, - { - "plugin": "exploratoryView", - "path": "x-pack/plugins/exploratory_view/public/application/index.tsx" - }, - { - "plugin": "exploratoryView", - "path": "x-pack/plugins/exploratory_view/public/application/index.tsx" - }, - { - "plugin": "exploratoryView", - "path": "x-pack/plugins/exploratory_view/public/application/index.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/integrations/app.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/integrations/app.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/integrations/app.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" - }, - { - "plugin": "observability", - "path": "x-pack/plugins/observability/public/application/index.tsx" - }, - { - "plugin": "observability", - "path": "x-pack/plugins/observability/public/application/index.tsx" - }, - { - "plugin": "observability", - "path": "x-pack/plugins/observability/public/application/index.tsx" - }, { "plugin": "licenseManagement", "path": "x-pack/plugins/license_management/public/shared_imports.ts" @@ -1396,6 +1352,18 @@ "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/data_comparison/data_comparison_app_state.tsx" }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" @@ -1444,6 +1412,54 @@ "plugin": "ml", "path": "x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx" }, + { + "plugin": "exploratoryView", + "path": "x-pack/plugins/exploratory_view/public/application/index.tsx" + }, + { + "plugin": "exploratoryView", + "path": "x-pack/plugins/exploratory_view/public/application/index.tsx" + }, + { + "plugin": "exploratoryView", + "path": "x-pack/plugins/exploratory_view/public/application/index.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/integrations/app.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/integrations/app.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/integrations/app.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/application/index.tsx" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/application/index.tsx" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/application/index.tsx" + }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/apps/common_providers.tsx" @@ -1576,22 +1592,6 @@ "plugin": "expressionShape", "path": "src/plugins/expression_shape/public/expression_renderers/progress_renderer.tsx" }, - { - "plugin": "indexManagement", - "path": "x-pack/plugins/index_management/public/shared_imports.ts" - }, - { - "plugin": "indexManagement", - "path": "x-pack/plugins/index_management/public/application/index.tsx" - }, - { - "plugin": "indexManagement", - "path": "x-pack/plugins/index_management/public/application/index.tsx" - }, - { - "plugin": "indexManagement", - "path": "x-pack/plugins/index_management/public/application/index.tsx" - }, { "plugin": "crossClusterReplication", "path": "x-pack/plugins/cross_cluster_replication/public/shared_imports.ts" @@ -1856,18 +1856,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/app/app.tsx" }, - { - "plugin": "serverlessSearch", - "path": "x-pack/plugins/serverless_search/public/application/indexing_api.tsx" - }, - { - "plugin": "serverlessSearch", - "path": "x-pack/plugins/serverless_search/public/application/indexing_api.tsx" - }, - { - "plugin": "serverlessSearch", - "path": "x-pack/plugins/serverless_search/public/application/indexing_api.tsx" - }, { "plugin": "snapshotRestore", "path": "x-pack/plugins/snapshot_restore/public/shared_imports.ts" @@ -2789,6 +2777,18 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx" }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx" + }, { "plugin": "exploratoryView", "path": "x-pack/plugins/exploratory_view/public/application/index.tsx" @@ -2873,18 +2873,6 @@ "plugin": "observability", "path": "x-pack/plugins/observability/public/application/index.tsx" }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx" - }, { "plugin": "apm", "path": "x-pack/plugins/apm/public/components/routing/app_root/index.tsx" @@ -3143,16 +3131,60 @@ "path": "src/plugins/data/public/search/search_service.ts" }, { - "plugin": "data", - "path": "src/plugins/data/public/search/search_service.ts" + "plugin": "data", + "path": "src/plugins/data/public/search/search_service.ts" + }, + { + "plugin": "licensing", + "path": "x-pack/plugins/licensing/public/expired_banner.tsx" + }, + { + "plugin": "licensing", + "path": "x-pack/plugins/licensing/public/expired_banner.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/session/session_expiration_toast.tsx" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/session/session_expiration_toast.tsx" + }, + { + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/saved_object/helpers/confirm_modal_promise.tsx" + }, + { + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/saved_object/helpers/confirm_modal_promise.tsx" + }, + { + "plugin": "runtimeFields", + "path": "x-pack/plugins/runtime_fields/public/shared_imports.ts" + }, + { + "plugin": "runtimeFields", + "path": "x-pack/plugins/runtime_fields/public/load_editor.tsx" + }, + { + "plugin": "runtimeFields", + "path": "x-pack/plugins/runtime_fields/public/load_editor.tsx" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/saved_object/helpers/confirm_modal_promise.tsx" + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/saved_object/helpers/confirm_modal_promise.tsx" + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx" }, { "plugin": "dataViewEditor", @@ -3182,30 +3214,6 @@ "plugin": "embeddable", "path": "src/plugins/embeddable/public/add_panel_flyout/open_add_panel_flyout.tsx" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/editor/open_add_data_control_flyout.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/editor/open_add_data_control_flyout.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/editor/open_edit_control_group_flyout.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/editor/open_edit_control_group_flyout.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/actions/edit_control_action.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/actions/edit_control_action.tsx" - }, { "plugin": "visualizations", "path": "src/plugins/visualizations/public/utils/saved_objects_utils/confirm_modal_promise.tsx" @@ -3238,6 +3246,30 @@ "plugin": "visualizations", "path": "src/plugins/visualizations/public/visualize_app/index.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/control_group/editor/open_add_data_control_flyout.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/control_group/editor/open_add_data_control_flyout.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/control_group/editor/open_edit_control_group_flyout.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/control_group/editor/open_edit_control_group_flyout.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/control_group/actions/edit_control_action.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/control_group/actions/edit_control_action.tsx" + }, { "plugin": "dashboard", "path": "src/plugins/dashboard/public/dashboard_container/embeddable/api/show_settings.tsx" @@ -3294,14 +3326,6 @@ "plugin": "dashboard", "path": "src/plugins/dashboard/public/dashboard_listing/dashboard_listing_table.tsx" }, - { - "plugin": "licensing", - "path": "x-pack/plugins/licensing/public/expired_banner.tsx" - }, - { - "plugin": "licensing", - "path": "x-pack/plugins/licensing/public/expired_banner.tsx" - }, { "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/public/components/edition_modal/open_modal.tsx" @@ -3322,14 +3346,6 @@ "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/public/components/assign_flyout/open_assign_flyout.tsx" }, - { - "plugin": "eventAnnotation", - "path": "src/plugins/event_annotation/public/get_table_list.tsx" - }, - { - "plugin": "eventAnnotation", - "path": "src/plugins/event_annotation/public/get_table_list.tsx" - }, { "plugin": "dataViewFieldEditor", "path": "src/plugins/data_view_field_editor/public/shared_imports.ts" @@ -3342,6 +3358,14 @@ "plugin": "dataViewFieldEditor", "path": "src/plugins/data_view_field_editor/public/open_delete_modal.tsx" }, + { + "plugin": "eventAnnotation", + "path": "src/plugins/event_annotation/public/get_table_list.tsx" + }, + { + "plugin": "eventAnnotation", + "path": "src/plugins/event_annotation/public/get_table_list.tsx" + }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/persistence/saved_objects_utils/confirm_modal_promise.tsx" @@ -3374,22 +3398,6 @@ "plugin": "lens", "path": "x-pack/plugins/lens/public/trigger_actions/open_lens_config/helpers.ts" }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/account_management/account_management_app.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/session/session_expiration_toast.tsx" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/public/session/session_expiration_toast.tsx" - }, { "plugin": "triggersActionsUi", "path": "x-pack/plugins/triggers_actions_ui/public/application/hooks/use_bulk_edit_response.tsx" @@ -3458,6 +3466,30 @@ "plugin": "observabilityShared", "path": "x-pack/plugins/observability_shared/public/components/header_menu/header_menu_portal.tsx" }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/public/services/telemetry_notifications/render_opt_in_status_notice_banner.tsx" + }, + { + "plugin": "telemetry", + "path": "src/plugins/telemetry/public/services/telemetry_notifications/render_opt_in_status_notice_banner.tsx" + }, + { + "plugin": "advancedSettings", + "path": "src/plugins/advanced_settings/public/management_app/components/form/form.tsx" + }, + { + "plugin": "advancedSettings", + "path": "src/plugins/advanced_settings/public/management_app/components/form/form.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/render_app.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/render_app.tsx" + }, { "plugin": "exploratoryView", "path": "x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/header/add_to_case_action.tsx" @@ -3562,30 +3594,6 @@ "plugin": "observability", "path": "x-pack/plugins/observability/public/pages/overview/components/header_menu/header_menu_portal.tsx" }, - { - "plugin": "telemetry", - "path": "src/plugins/telemetry/public/services/telemetry_notifications/render_opt_in_status_notice_banner.tsx" - }, - { - "plugin": "telemetry", - "path": "src/plugins/telemetry/public/services/telemetry_notifications/render_opt_in_status_notice_banner.tsx" - }, - { - "plugin": "advancedSettings", - "path": "src/plugins/advanced_settings/public/management_app/components/form/form.tsx" - }, - { - "plugin": "advancedSettings", - "path": "src/plugins/advanced_settings/public/management_app/components/form/form.tsx" - }, - { - "plugin": "maps", - "path": "x-pack/plugins/maps/public/render_app.tsx" - }, - { - "plugin": "maps", - "path": "x-pack/plugins/maps/public/render_app.tsx" - }, { "plugin": "banners", "path": "x-pack/plugins/banners/public/plugin.tsx" @@ -3686,26 +3694,6 @@ "plugin": "cloudSecurityPosture", "path": "x-pack/plugins/cloud_security_posture/public/components/take_action.tsx" }, - { - "plugin": "runtimeFields", - "path": "x-pack/plugins/runtime_fields/public/shared_imports.ts" - }, - { - "plugin": "runtimeFields", - "path": "x-pack/plugins/runtime_fields/public/load_editor.tsx" - }, - { - "plugin": "runtimeFields", - "path": "x-pack/plugins/runtime_fields/public/load_editor.tsx" - }, - { - "plugin": "indexManagement", - "path": "x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx" - }, - { - "plugin": "indexManagement", - "path": "x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx" - }, { "plugin": "dashboardEnhanced", "path": "x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx" @@ -3918,122 +3906,6 @@ "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/apps/synthetics/components/test_now_mode/manual_test_run_mode/simple_test_results.tsx" }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/components/toast_notification_text.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/components/toast_notification_text.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_reset_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_reset_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_reset_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_schedule_now_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_schedule_now_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_start_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_start_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_stop_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_stop_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_reauthorize_transform.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/hooks/use_reauthorize_transform.tsx" - }, { "plugin": "uptime", "path": "x-pack/plugins/uptime/public/legacy_uptime/lib/alert_types/alert_messages.tsx" diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index bdcdf066e33f0..ed71a3d96bde8 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 0a4c1ffb692bf..2a1c0a51e660c 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-08-25 +date: 2023-09-04 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 2a9f92dcb4892..60a832a0977dc 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index aea5fe81dc435..29021cfa454fa 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-08-25 +date: 2023-09-04 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 48007a519a242..65885b8a1e469 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-08-25 +date: 2023-09-04 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 3f7dd45c85723..a1a342aaad5dc 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-08-25 +date: 2023-09-04 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 9e94dad897ead..a11ca0da7cead 100644 --- a/api_docs/licensing.devdocs.json +++ b/api_docs/licensing.devdocs.json @@ -810,14 +810,14 @@ "plugin": "security", "path": "x-pack/plugins/security/public/plugin.tsx" }, - { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/plugin.tsx" - }, { "plugin": "licenseManagement", "path": "x-pack/plugins/license_management/public/plugin.ts" }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/plugin.tsx" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/public/plugin.ts" @@ -2190,6 +2190,14 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/plugin.ts" }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/handlers/action/create_action_service.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts" + }, { "plugin": "remoteClusters", "path": "x-pack/plugins/remote_clusters/server/plugin.ts" @@ -2206,10 +2214,6 @@ "plugin": "mapsEms", "path": "src/plugins/maps_ems/server/index.ts" }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/handlers/action/create_action_service.ts" - }, { "plugin": "painlessLab", "path": "x-pack/plugins/painless_lab/server/services/license.ts" @@ -2222,10 +2226,6 @@ "plugin": "searchprofiler", "path": "x-pack/plugins/searchprofiler/server/plugin.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts" - }, { "plugin": "snapshotRestore", "path": "x-pack/plugins/snapshot_restore/server/services/license.ts" diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 4eb1e1caaf760..508c86da553db 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.devdocs.json b/api_docs/lists.devdocs.json index ef489757d203b..1dce5bcba81d2 100644 --- a/api_docs/lists.devdocs.json +++ b/api_docs/lists.devdocs.json @@ -2594,6 +2594,24 @@ "The contents of the bootstrap response from Elasticsearch" ] }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.deleteLegacyListTemplateIfExists", + "type": "Function", + "tags": [], + "label": "deleteLegacyListTemplateIfExists", + "description": [ + "\nChecks if legacy lists template exists and delete it" + ], + "signature": [ + "() => Promise" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "lists", "id": "def-server.ListClient.deleteLegacyListItemTemplate", @@ -2614,6 +2632,24 @@ "The contents of the bootstrap response from Elasticsearch" ] }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.deleteLegacyListItemTemplateIfExists", + "type": "Function", + "tags": [], + "label": "deleteLegacyListItemTemplateIfExists", + "description": [ + "\nChecks if legacy list item template exists and delete it" + ], + "signature": [ + "() => Promise" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "lists", "id": "def-server.ListClient.deleteListItem", diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 2b990749cbce6..247232136211d 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-detection-engine](https://github.com/orgs/elastic/tea | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 222 | 0 | 96 | 51 | +| 224 | 0 | 96 | 51 | ## Client diff --git a/api_docs/log_explorer.devdocs.json b/api_docs/log_explorer.devdocs.json new file mode 100644 index 0000000000000..742f9c0f72bfa --- /dev/null +++ b/api_docs/log_explorer.devdocs.json @@ -0,0 +1,76 @@ +{ + "id": "logExplorer", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [], + "setup": { + "parentPluginId": "logExplorer", + "id": "def-public.LogExplorerPluginSetup", + "type": "Type", + "tags": [], + "label": "LogExplorerPluginSetup", + "description": [], + "signature": [ + "void" + ], + "path": "x-pack/plugins/log_explorer/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "lifecycle": "setup", + "initialIsOpen": true + }, + "start": { + "parentPluginId": "logExplorer", + "id": "def-public.LogExplorerPluginStart", + "type": "Interface", + "tags": [], + "label": "LogExplorerPluginStart", + "description": [], + "path": "x-pack/plugins/log_explorer/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "logExplorer", + "id": "def-public.LogExplorerPluginStart.LogExplorer", + "type": "CompoundType", + "tags": [], + "label": "LogExplorer", + "description": [], + "signature": [ + "React.ComponentClass<", + "LogExplorerProps", + ", any> | React.FunctionComponent<", + "LogExplorerProps", + ">" + ], + "path": "x-pack/plugins/log_explorer/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "start", + "initialIsOpen": true + } + }, + "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/log_explorer.mdx b/api_docs/log_explorer.mdx new file mode 100644 index 0000000000000..6004083673791 --- /dev/null +++ b/api_docs/log_explorer.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: kibLogExplorerPluginApi +slug: /kibana-dev-docs/api/logExplorer +title: "logExplorer" +image: https://source.unsplash.com/400x175/?github +description: API docs for the logExplorer plugin +date: 2023-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logExplorer'] +--- +import logExplorerObj from './log_explorer.devdocs.json'; + +This plugin provides a LogExplorer component using the Discover customization framework, offering several affordances specifically designed for log consumption. + +Contact [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 3 | 0 | 3 | 1 | + +## Client + +### Setup + + +### Start + + diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index 5b07deb62acce..baad071884889 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-08-25 +date: 2023-09-04 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 70ca84de56daa..b068a07ce37ac 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 64cd4f63922b3..b1752003c6291 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 1edb84988fc64..dc183c290a096 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 5b2629a59343f..4b22ee129531d 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-08-25 +date: 2023-09-04 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 26958fd847084..6fbf2b6aec84f 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.devdocs.json b/api_docs/monitoring_collection.devdocs.json index 79950746cd8e0..76ebc220d46f2 100644 --- a/api_docs/monitoring_collection.devdocs.json +++ b/api_docs/monitoring_collection.devdocs.json @@ -54,9 +54,9 @@ "signature": [ "{ [Key in keyof Required]: Required[Key] extends (infer U)[] ? { type: \"array\"; items: ", "RecursiveMakeSchemaFrom", - "; } : ", + "; } : ", "RecursiveMakeSchemaFrom", - "[Key]>; }" + "[Key], false>; }" ], "path": "x-pack/plugins/monitoring_collection/server/plugin.ts", "deprecated": false, diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index a3b2daf2231c7..d541b6206bc4e 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-08-25 +date: 2023-09-04 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 5ea03c1d04147..78bb664c118c8 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-08-25 +date: 2023-09-04 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 0afdaa8717141..8eb97e2f58550 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.devdocs.json b/api_docs/no_data_page.devdocs.json new file mode 100644 index 0000000000000..0bbeb2e20defc --- /dev/null +++ b/api_docs/no_data_page.devdocs.json @@ -0,0 +1,49 @@ +{ + "id": "noDataPage", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [], + "setup": { + "parentPluginId": "noDataPage", + "id": "def-public.NoDataPagePluginStart", + "type": "Type", + "tags": [], + "label": "NoDataPagePluginStart", + "description": [], + "signature": [ + { + "pluginId": "noDataPage", + "scope": "public", + "docId": "kibNoDataPagePluginApi", + "section": "def-public.NoDataPagePluginSetup", + "text": "NoDataPagePluginSetup" + } + ], + "path": "src/plugins/no_data_page/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "lifecycle": "setup", + "initialIsOpen": true + } + }, + "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/no_data_page.mdx b/api_docs/no_data_page.mdx new file mode 100644 index 0000000000000..1973a7ab3a0e7 --- /dev/null +++ b/api_docs/no_data_page.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: kibNoDataPagePluginApi +slug: /kibana-dev-docs/api/noDataPage +title: "noDataPage" +image: https://source.unsplash.com/400x175/?github +description: API docs for the noDataPage plugin +date: 2023-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] +--- +import noDataPageObj from './no_data_page.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 | +|-------------------|-----------|------------------------|-----------------| +| 3 | 0 | 3 | 0 | + +## Client + +### Setup + + diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 8d43d096fc82a..9f595734c1cd6 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-08-25 +date: 2023-09-04 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 3816bbd3603fd..e910e74323d61 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -8627,72 +8627,6 @@ "section": "def-server.ObservabilityRouteCreateOptions", "text": "ObservabilityRouteCreateOptions" }, - "; \"GET /internal/observability/slos/{id}/_diagnosis\": { endpoint: \"GET /internal/observability/slos/{id}/_diagnosis\"; 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<{ sloResources: { \".slo-observability.sli\": string; \".slo-observability.sli-mappings\": string; \".slo-observability.sli-settings\": string; \".slo-observability.sli.pipeline\": string; } | undefined; sloSummaryResources: { \".slo-observability.summary\": string; \".slo-observability.summary-mappings\": string; \".slo-observability.summary-settings\": string; } | undefined; slo: string | { 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; })[]; equation: string; }; total: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; equation: string; }; 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: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; type: \"rolling\"; } | { duration: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - " | undefined; }; settings: { syncDelay: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; frequency: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; }; revision: number; enabled: boolean; tags: string[]; createdAt: Date; updatedAt: Date; groupBy: string; }; sloTransformStats: ", - "TransformGetTransformStatsResponse", - "; sloSummaryTransformsStats: ", - "TransformGetTransformStatsResponse", - "; }>; } & ", - { - "pluginId": "observability", - "scope": "server", - "docId": "kibObservabilityPluginApi", - "section": "def-server.ObservabilityRouteCreateOptions", - "text": "ObservabilityRouteCreateOptions" - }, "; \"GET /internal/observability/slos/_diagnosis\": { endpoint: \"GET /internal/observability/slos/_diagnosis\"; params?: undefined; handler: ({}: ", { "pluginId": "observability", @@ -8703,11 +8637,11 @@ }, ") => Promise<{ licenseAndFeatures: ", "PublicLicenseJSON", - "; userPrivileges: ", - "SecurityGetUserPrivilegesResponse", - "; sloResources: { \".slo-observability.sli\": string; \".slo-observability.sli-mappings\": string; \".slo-observability.sli-settings\": string; \".slo-observability.sli.pipeline\": string; } | undefined; sloSummaryResources: { \".slo-observability.summary\": string; \".slo-observability.summary-mappings\": string; \".slo-observability.summary-settings\": string; } | undefined; sloSummaryTransformsStats: ", - "TransformGetTransformStatsResponse", - "; }>; } & ", + "; userPrivileges: { write: ", + "SecurityHasPrivilegesResponse", + "; read: ", + "SecurityHasPrivilegesResponse", + "; }; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -10399,72 +10333,6 @@ "section": "def-server.ObservabilityRouteCreateOptions", "text": "ObservabilityRouteCreateOptions" }, - "; \"GET /internal/observability/slos/{id}/_diagnosis\": { endpoint: \"GET /internal/observability/slos/{id}/_diagnosis\"; 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<{ sloResources: { \".slo-observability.sli\": string; \".slo-observability.sli-mappings\": string; \".slo-observability.sli-settings\": string; \".slo-observability.sli.pipeline\": string; } | undefined; sloSummaryResources: { \".slo-observability.summary\": string; \".slo-observability.summary-mappings\": string; \".slo-observability.summary-settings\": string; } | undefined; slo: string | { 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; })[]; equation: string; }; total: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; equation: string; }; 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: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; type: \"rolling\"; } | { duration: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - " | undefined; }; settings: { syncDelay: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; frequency: ", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - "; }; revision: number; enabled: boolean; tags: string[]; createdAt: Date; updatedAt: Date; groupBy: string; }; sloTransformStats: ", - "TransformGetTransformStatsResponse", - "; sloSummaryTransformsStats: ", - "TransformGetTransformStatsResponse", - "; }>; } & ", - { - "pluginId": "observability", - "scope": "server", - "docId": "kibObservabilityPluginApi", - "section": "def-server.ObservabilityRouteCreateOptions", - "text": "ObservabilityRouteCreateOptions" - }, "; \"GET /internal/observability/slos/_diagnosis\": { endpoint: \"GET /internal/observability/slos/_diagnosis\"; params?: undefined; handler: ({}: ", { "pluginId": "observability", @@ -10475,11 +10343,11 @@ }, ") => Promise<{ licenseAndFeatures: ", "PublicLicenseJSON", - "; userPrivileges: ", - "SecurityGetUserPrivilegesResponse", - "; sloResources: { \".slo-observability.sli\": string; \".slo-observability.sli-mappings\": string; \".slo-observability.sli-settings\": string; \".slo-observability.sli.pipeline\": string; } | undefined; sloSummaryResources: { \".slo-observability.summary\": string; \".slo-observability.summary-mappings\": string; \".slo-observability.summary-settings\": string; } | undefined; sloSummaryTransformsStats: ", - "TransformGetTransformStatsResponse", - "; }>; } & ", + "; userPrivileges: { write: ", + "SecurityHasPrivilegesResponse", + "; read: ", + "SecurityHasPrivilegesResponse", + "; }; }>; } & ", { "pluginId": "observability", "scope": "server", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index eef738f7ece3c..b1c722815ff86 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-08-25 +date: 2023-09-04 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 add55aaff694a..59f2dcee727e4 100644 --- a/api_docs/observability_a_i_assistant.devdocs.json +++ b/api_docs/observability_a_i_assistant.devdocs.json @@ -367,7 +367,31 @@ "label": "APIReturnType", "description": [], "signature": [ - "{ \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", + "{ \"POST /internal/observability_ai_assistant/functions/alerts\": { endpoint: \"POST /internal/observability_ai_assistant/functions/alerts\"; params?: ", + "TypeC", + "<{ body: ", + "IntersectionC", + "<[", + "TypeC", + "<{ featureIds: ", + "ArrayC", + "<", + "StringC", + ">; start: ", + "StringC", + "; end: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; includeRecovered: ", + "Type", + "; }>]>; }> | undefined; handler: ({}: ", + "ObservabilityAIAssistantRouteHandlerResources", + " & { 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", ") => Promise<{ ready: boolean; error?: any; deployment_state?: string | undefined; allocation_state?: string | undefined; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -405,7 +429,13 @@ "Type", "; public: ", "Type", - "; }>; }> | undefined; handler: ({}: ", + "; labels: ", + "RecordC", + "<", + "StringC", + ", ", + "StringC", + ">; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", " & { params: { body: { id: string; text: ", "Branded", @@ -417,13 +447,15 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; }; }; }) => Promise; } & ", + ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; labels: { [x: string]: string; }; }; }; }) => Promise; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/recall\": { endpoint: \"POST /internal/observability_ai_assistant/functions/recall\"; params?: ", "TypeC", "<{ body: ", "TypeC", - "<{ query: ", + "<{ queries: ", + "ArrayC", + "<", "BrandC", "<", "StringC", @@ -435,9 +467,9 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; }>; }> | undefined; handler: ({}: ", + ">>; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", - " & { params: { body: { query: ", + " & { params: { body: { queries: ", "Branded", "; }; }; }) => Promise<{ entries: ", + ">[]; }; }; }) => Promise<{ entries: Pick<", "KnowledgeBaseEntry", - "[]; }>; } & ", + ", \"id\" | \"text\">[]; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/elasticsearch\": { endpoint: \"POST /internal/observability_ai_assistant/functions/elasticsearch\"; params?: ", "TypeC", @@ -700,7 +732,31 @@ "label": "ObservabilityAIAssistantAPIClientRequestParamsOf", "description": [], "signature": [ - "{ \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", + "{ \"POST /internal/observability_ai_assistant/functions/alerts\": { endpoint: \"POST /internal/observability_ai_assistant/functions/alerts\"; params?: ", + "TypeC", + "<{ body: ", + "IntersectionC", + "<[", + "TypeC", + "<{ featureIds: ", + "ArrayC", + "<", + "StringC", + ">; start: ", + "StringC", + "; end: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; includeRecovered: ", + "Type", + "; }>]>; }> | undefined; handler: ({}: ", + "ObservabilityAIAssistantRouteHandlerResources", + " & { 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", ") => Promise<{ ready: boolean; error?: any; deployment_state?: string | undefined; allocation_state?: string | undefined; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -738,7 +794,13 @@ "Type", "; public: ", "Type", - "; }>; }> | undefined; handler: ({}: ", + "; labels: ", + "RecordC", + "<", + "StringC", + ", ", + "StringC", + ">; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", " & { params: { body: { id: string; text: ", "Branded", @@ -750,13 +812,15 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; }; }; }) => Promise; } & ", + ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; labels: { [x: string]: string; }; }; }; }) => Promise; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/recall\": { endpoint: \"POST /internal/observability_ai_assistant/functions/recall\"; params?: ", "TypeC", "<{ body: ", "TypeC", - "<{ query: ", + "<{ queries: ", + "ArrayC", + "<", "BrandC", "<", "StringC", @@ -768,9 +832,9 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; }>; }> | undefined; handler: ({}: ", + ">>; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", - " & { params: { body: { query: ", + " & { params: { body: { queries: ", "Branded", "; }; }; }) => Promise<{ entries: ", + ">[]; }; }; }) => Promise<{ entries: Pick<", "KnowledgeBaseEntry", - "[]; }>; } & ", + ", \"id\" | \"text\">[]; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/elasticsearch\": { endpoint: \"POST /internal/observability_ai_assistant/functions/elasticsearch\"; params?: ", "TypeC", @@ -1041,7 +1105,7 @@ "label": "ObservabilityAIAssistantAPIEndpoint", "description": [], "signature": [ - "\"POST /internal/observability_ai_assistant/chat\" | \"GET /internal/observability_ai_assistant/conversation/{conversationId}\" | \"POST /internal/observability_ai_assistant/conversations\" | \"POST /internal/observability_ai_assistant/conversation\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}/auto_title\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}/title\" | \"DELETE /internal/observability_ai_assistant/conversation/{conversationId}\" | \"GET /internal/observability_ai_assistant/connectors\" | \"POST /internal/observability_ai_assistant/functions/elasticsearch\" | \"POST /internal/observability_ai_assistant/functions/recall\" | \"POST /internal/observability_ai_assistant/functions/summarise\" | \"POST /internal/observability_ai_assistant/functions/setup_kb\" | \"GET /internal/observability_ai_assistant/functions/kb_status\"" + "\"POST /internal/observability_ai_assistant/chat\" | \"GET /internal/observability_ai_assistant/conversation/{conversationId}\" | \"POST /internal/observability_ai_assistant/conversations\" | \"POST /internal/observability_ai_assistant/conversation\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}/auto_title\" | \"PUT /internal/observability_ai_assistant/conversation/{conversationId}/title\" | \"DELETE /internal/observability_ai_assistant/conversation/{conversationId}\" | \"GET /internal/observability_ai_assistant/connectors\" | \"POST /internal/observability_ai_assistant/functions/elasticsearch\" | \"POST /internal/observability_ai_assistant/functions/recall\" | \"POST /internal/observability_ai_assistant/functions/summarise\" | \"POST /internal/observability_ai_assistant/functions/setup_kb\" | \"GET /internal/observability_ai_assistant/functions/kb_status\" | \"POST /internal/observability_ai_assistant/functions/alerts\"" ], "path": "x-pack/plugins/observability_ai_assistant/public/api/index.ts", "deprecated": false, @@ -1139,7 +1203,31 @@ "label": "ObservabilityAIAssistantServerRouteRepository", "description": [], "signature": [ - "{ \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", + "{ \"POST /internal/observability_ai_assistant/functions/alerts\": { endpoint: \"POST /internal/observability_ai_assistant/functions/alerts\"; params?: ", + "TypeC", + "<{ body: ", + "IntersectionC", + "<[", + "TypeC", + "<{ featureIds: ", + "ArrayC", + "<", + "StringC", + ">; start: ", + "StringC", + "; end: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; includeRecovered: ", + "Type", + "; }>]>; }> | undefined; handler: ({}: ", + "ObservabilityAIAssistantRouteHandlerResources", + " & { 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", ") => Promise<{ ready: boolean; error?: any; deployment_state?: string | undefined; allocation_state?: string | undefined; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -1177,7 +1265,13 @@ "Type", "; public: ", "Type", - "; }>; }> | undefined; handler: ({}: ", + "; labels: ", + "RecordC", + "<", + "StringC", + ", ", + "StringC", + ">; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", " & { params: { body: { id: string; text: ", "Branded", @@ -1189,13 +1283,15 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; }; }; }) => Promise; } & ", + ">; confidence: \"medium\" | \"high\" | \"low\"; is_correction: boolean; public: boolean; labels: { [x: string]: string; }; }; }; }) => Promise; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/recall\": { endpoint: \"POST /internal/observability_ai_assistant/functions/recall\"; params?: ", "TypeC", "<{ body: ", "TypeC", - "<{ query: ", + "<{ queries: ", + "ArrayC", + "<", "BrandC", "<", "StringC", @@ -1207,9 +1303,9 @@ "section": "def-common.NonEmptyStringBrand", "text": "NonEmptyStringBrand" }, - ">; }>; }> | undefined; handler: ({}: ", + ">>; }>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", - " & { params: { body: { query: ", + " & { params: { body: { queries: ", "Branded", "; }; }; }) => Promise<{ entries: ", + ">[]; }; }; }) => Promise<{ entries: Pick<", "KnowledgeBaseEntry", - "[]; }>; } & ", + ", \"id\" | \"text\">[]; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"POST /internal/observability_ai_assistant/functions/elasticsearch\": { endpoint: \"POST /internal/observability_ai_assistant/functions/elasticsearch\"; params?: ", "TypeC", diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 97e26bd0c43b0..ed74b23cb89cd 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index b5dbd0add550e..466e27fd88687 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.devdocs.json b/api_docs/observability_shared.devdocs.json index 0a612b6ac7f72..2bfd9c96c19c3 100644 --- a/api_docs/observability_shared.devdocs.json +++ b/api_docs/observability_shared.devdocs.json @@ -682,7 +682,7 @@ "DisambiguateSet", ", Omit, \"href\">> & Omit, \"href\">) | (", "DisambiguateSet", - ", \"href\">, React.ButtonHTMLAttributes> & React.ButtonHTMLAttributes))), \"color\" | \"onClick\" | \"rel\" | \"target\"> & { size?: \"m\" | \"s\" | \"xs\" | \"l\" | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; label: React.ReactNode; isActive?: boolean | undefined; isDisabled?: boolean | undefined; href?: string | undefined; target?: string | undefined; rel?: string | undefined; iconType?: ", + ", \"href\">, React.ButtonHTMLAttributes> & React.ButtonHTMLAttributes))), \"color\" | \"onClick\" | \"rel\" | \"target\"> & { size?: \"m\" | \"s\" | \"l\" | \"xs\" | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; label: React.ReactNode; isActive?: boolean | undefined; isDisabled?: boolean | undefined; href?: string | undefined; target?: string | undefined; rel?: string | undefined; iconType?: ", "IconType", " | undefined; iconProps?: Omit<", "EuiIconProps", @@ -721,7 +721,7 @@ "DisambiguateSet", ", Omit, \"href\">> & Omit, \"href\">) | (", "DisambiguateSet", - ", \"href\">, React.ButtonHTMLAttributes> & React.ButtonHTMLAttributes))), \"color\" | \"onClick\" | \"rel\" | \"target\"> & { size?: \"m\" | \"s\" | \"xs\" | \"l\" | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; label: React.ReactNode; isActive?: boolean | undefined; isDisabled?: boolean | undefined; href?: string | undefined; target?: string | undefined; rel?: string | undefined; iconType?: ", + ", \"href\">, React.ButtonHTMLAttributes> & React.ButtonHTMLAttributes))), \"color\" | \"onClick\" | \"rel\" | \"target\"> & { size?: \"m\" | \"s\" | \"l\" | \"xs\" | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; label: React.ReactNode; isActive?: boolean | undefined; isDisabled?: boolean | undefined; href?: string | undefined; target?: string | undefined; rel?: string | undefined; iconType?: ", "IconType", " | undefined; iconProps?: Omit<", "EuiIconProps", @@ -752,7 +752,7 @@ "CommonProps", " & Omit, \"color\"> & { bordered?: boolean | undefined; flush?: boolean | undefined; gutterSize?: \"m\" | \"none\" | \"s\" | undefined; listItems?: ", "EuiListGroupItemProps", - "[] | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; size?: \"m\" | \"s\" | \"xs\" | \"l\" | undefined; maxWidth?: boolean | ", + "[] | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; size?: \"m\" | \"s\" | \"l\" | \"xs\" | undefined; maxWidth?: boolean | ", "Property", ".MaxWidth | undefined; showToolTips?: boolean | undefined; wrapText?: boolean | undefined; ariaLabelledby?: string | undefined; }) => JSX.Element" ], @@ -772,7 +772,7 @@ "CommonProps", " & Omit, \"color\"> & { bordered?: boolean | undefined; flush?: boolean | undefined; gutterSize?: \"m\" | \"none\" | \"s\" | undefined; listItems?: ", "EuiListGroupItemProps", - "[] | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; size?: \"m\" | \"s\" | \"xs\" | \"l\" | undefined; maxWidth?: boolean | ", + "[] | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; size?: \"m\" | \"s\" | \"l\" | \"xs\" | undefined; maxWidth?: boolean | ", "Property", ".MaxWidth | undefined; showToolTips?: boolean | undefined; wrapText?: boolean | undefined; ariaLabelledby?: string | undefined; }" ], @@ -2548,7 +2548,7 @@ "DisambiguateSet", ", Omit, \"href\">> & Omit, \"href\">) | (", "DisambiguateSet", - ", \"href\">, React.ButtonHTMLAttributes> & React.ButtonHTMLAttributes))), \"color\" | \"onClick\" | \"rel\" | \"target\"> & { size?: \"m\" | \"s\" | \"xs\" | \"l\" | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; label: React.ReactNode; isActive?: boolean | undefined; isDisabled?: boolean | undefined; href?: string | undefined; target?: string | undefined; rel?: string | undefined; iconType?: ", + ", \"href\">, React.ButtonHTMLAttributes> & React.ButtonHTMLAttributes))), \"color\" | \"onClick\" | \"rel\" | \"target\"> & { size?: \"m\" | \"s\" | \"l\" | \"xs\" | undefined; color?: \"text\" | \"subdued\" | \"primary\" | undefined; label: React.ReactNode; isActive?: boolean | undefined; isDisabled?: boolean | undefined; href?: string | undefined; target?: string | undefined; rel?: string | undefined; iconType?: ", "IconType", " | undefined; iconProps?: Omit<", "EuiIconProps", diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index a961705d499d8..3dd063884758a 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index d806be1270423..7a78e60ca9c54 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 01fb7a421113c..14fc828885c33 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,29 +15,29 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 666 | 555 | 39 | +| 674 | 564 | 39 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 72232 | 224 | 61695 | 1490 | +| 72500 | 223 | 61891 | 1513 | ## Plugin Directory | Plugin name           | Maintaining team | Description | API Cnt | Any Cnt | Missing
comments | Missing
exports | |--------------|----------------|-----------|--------------|----------|---------------|--------| -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 267 | 0 | 261 | 28 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 267 | 0 | 261 | 30 | | | [@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. | 61 | 1 | 3 | 0 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 786 | 1 | 755 | 46 | -| | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 29 | 0 | 29 | 118 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 790 | 1 | 759 | 49 | +| | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 29 | 0 | 29 | 119 | | | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | - | 9 | 0 | 9 | 0 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | Asset manager plugin for entity assets (inventory, topology, etc) | 2 | 0 | 2 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 9 | 0 | 9 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Considering using bfetch capabilities when fetching large amounts of data. This services supports batching HTTP requests and streaming responses back. | 91 | 1 | 75 | 2 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Canvas application to Kibana | 9 | 0 | 8 | 3 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | The Case management system in Kibana | 94 | 0 | 75 | 27 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | The Case management system in Kibana | 104 | 0 | 84 | 27 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 268 | 2 | 253 | 10 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 72 | 0 | 16 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | Chat available on Elastic Cloud deployments for quicker assistance. | 3 | 0 | 2 | 0 | @@ -57,17 +57,17 @@ 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 | 101 | 0 | 98 | 9 | | | [@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. | 3308 | 33 | 2581 | 26 | +| | [@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. | 3311 | 33 | 2584 | 26 | | | [@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 | 16 | 0 | 7 | 0 | | | [@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. | 1034 | 0 | 254 | 2 | | | [@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/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 12 | 0 | 10 | 3 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 79 | 0 | 52 | 15 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 98 | 0 | 71 | 15 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | -| discoverLogExplorer | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | This plugin exposes and registers Logs+ features. | 0 | 0 | 0 | 0 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | APIs used to assess the quality of data in Elasticsearch indexes | 2 | 0 | 0 | 0 | +| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | Server APIs for the Elastic AI Assistant | 4 | 0 | 2 | 0 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 542 | 1 | 442 | 7 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides encryption and decryption utilities for saved objects containing sensitive information. | 51 | 0 | 44 | 0 | @@ -89,7 +89,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'shape' function and renderer to expressions | 148 | 0 | 146 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Tagcloud plugin adds a `tagcloud` renderer and function to the expression plugin. The renderer will display the `Wordcloud` chart. | 6 | 0 | 6 | 2 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression XY plugin adds a `xy` renderer and function to the expression plugin. The renderer will display the `xy` chart. | 175 | 0 | 165 | 13 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds expression runtime to Kibana | 2205 | 17 | 1746 | 5 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds expression runtime to Kibana | 2208 | 17 | 1749 | 5 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 235 | 0 | 99 | 2 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Index pattern fields and ambiguous values formatters | 292 | 5 | 253 | 3 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | @@ -106,7 +106,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 147 | 0 | 108 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Image embeddable | 3 | 0 | 3 | 1 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 4 | 0 | 4 | 0 | -| | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 182 | 0 | 177 | 4 | +| | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 191 | 0 | 186 | 4 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | This plugin visualizes data from Filebeat and Metricbeat, and integrates with other Observability solutions | 45 | 0 | 42 | 11 | | ingestPipelines | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | | inputControlVis | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Input Control visualization to Kibana | 0 | 0 | 0 | 0 | @@ -121,7 +121,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 8 | 0 | 8 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 4 | 0 | 4 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 10 | -| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 222 | 0 | 96 | 51 | +| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 224 | 0 | 96 | 51 | +| | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | This plugin provides a LogExplorer component using the Discover customization framework, offering several affordances specifically designed for log consumption. | 3 | 0 | 3 | 1 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | Exposes the shared components and APIs to access and visualize logs. | 269 | 10 | 256 | 27 | | 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) | - | 47 | 0 | 47 | 7 | @@ -132,19 +133,22 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | - | 9 | 0 | 9 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 34 | 0 | 34 | 2 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 3 | 0 | 3 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 1 | | | [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) | - | 541 | 2 | 532 | 16 | | | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 42 | 0 | 39 | 7 | +| observabilityLogExplorer | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | This plugin exposes and registers observability log consumption features. | 0 | 0 | 0 | 0 | | | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | - | 14 | 0 | 14 | 0 | | | [@elastic/observability-ui](https://github.com/orgs/elastic/teams/observability-ui) | - | 277 | 1 | 276 | 11 | | | [@elastic/security-defend-workflows](https://github.com/orgs/elastic/teams/security-defend-workflows) | - | 24 | 0 | 24 | 7 | | painlessLab | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 218 | 2 | 164 | 11 | -| | [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) | - | 19 | 1 | 19 | 3 | +| | [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) | - | 17 | 1 | 17 | 3 | +| | [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) | - | 3 | 0 | 3 | 1 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 4 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 42 | 0 | 22 | 5 | | | [@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) | - | 264 | 0 | 235 | 14 | +| | [@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 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 129 | 2 | 118 | 4 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 25 | 0 | 25 | 0 | @@ -156,7 +160,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-reporting-services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Kibana Screenshotting Plugin | 27 | 0 | 8 | 5 | | 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 | 3 | 109 | 34 | +| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 170 | 0 | 104 | 32 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | ESS customizations for Security Solution. | 6 | 0 | 6 | 0 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | Serverless customizations for security. | 6 | 0 | 6 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | The core Serverless plugin, providing APIs to Serverless Project plugins. | 17 | 0 | 16 | 0 | @@ -174,7 +178,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@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 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 0 | 0 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 17 | 0 | 17 | 0 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 19 | 0 | 19 | 0 | | | [@elastic/protections-experience](https://github.com/orgs/elastic/teams/protections-experience) | Elastic threat intelligence helps you see if you are open to or have been subject to current or historical known threats | 30 | 0 | 14 | 5 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 257 | 1 | 213 | 22 | | | [@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 | @@ -182,8 +186,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 573 | 1 | 547 | 51 | | | [@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 | 206 | 0 | 140 | 9 | +| | [@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 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display. | 53 | 0 | 23 | 2 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 142 | 2 | 104 | 22 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 148 | 2 | 110 | 22 | | upgradeAssistant | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | | | [@elastic/uptime](https://github.com/orgs/elastic/teams/uptime) | This plugin visualizes data from Heartbeat, and integrates with other Observability solutions. | 1 | 0 | 1 | 0 | | urlDrilldown | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds drilldown implementations to Kibana | 0 | 0 | 0 | 0 | @@ -213,9 +218,10 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 11 | 5 | 11 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 33 | 0 | 0 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 20 | 0 | 0 | 0 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 16 | 0 | 15 | 0 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 25 | 0 | 25 | 0 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 8 | 0 | 7 | 1 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 24 | 3 | 24 | 0 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 23 | 0 | 22 | 0 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 29 | 0 | 29 | 0 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 10 | 0 | 9 | 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) | - | 19 | 0 | 0 | 0 | @@ -259,7 +265,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 8 | 0 | 1 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 20 | 0 | 19 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2 | 0 | 2 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 8 | 0 | 8 | 1 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 3 | 0 | 3 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 13 | 0 | 4 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 7 | 2 | @@ -291,9 +297,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 22 | 0 | 13 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 37 | 1 | 33 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 108 | 0 | 54 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 37 | 0 | 33 | 3 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 15 | 1 | 15 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 111 | 0 | 54 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 38 | 0 | 34 | 3 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 13 | 1 | 13 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 10 | 0 | 2 | 1 | @@ -352,8 +358,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 1 | 0 | 1 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 3 | 0 | 3 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 15 | 0 | 11 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 6 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 58 | 0 | 26 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 7 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 60 | 0 | 26 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 5 | 0 | 5 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 5 | 0 | 0 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 6 | 0 | @@ -362,7 +368,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 25 | 1 | 24 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 111 | 1 | 0 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 351 | 1 | 5 | 1 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 352 | 1 | 5 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 11 | 0 | 11 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 89 | 0 | 61 | 10 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | @@ -372,9 +378,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 73 | 0 | 40 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 26 | 0 | 23 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 124 | 0 | 90 | 46 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 125 | 0 | 91 | 46 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 12 | 0 | 12 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 548 | 1 | 122 | 4 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 547 | 1 | 121 | 4 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 69 | 0 | 69 | 4 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 14 | 0 | 14 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 36 | 0 | 6 | 0 | @@ -397,7 +403,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 32 | 1 | 16 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 18 | 1 | 17 | 3 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 6 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 153 | 0 | 142 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 155 | 0 | 144 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 8 | 0 | 8 | 2 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 7 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 6 | 0 | 6 | 0 | @@ -421,19 +427,19 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 9 | 1 | 9 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 101 | 0 | 85 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 15 | 0 | 9 | 0 | -| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 27 | 2 | 24 | 0 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 59 | 0 | 34 | 3 | +| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 29 | 2 | 25 | 0 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 65 | 0 | 38 | 3 | | | [@elastic/docs](https://github.com/orgs/elastic/teams/docs) | - | 73 | 0 | 73 | 2 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 1 | 0 | 1 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 39 | 0 | 26 | 5 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 19 | 0 | 11 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 35125 | 0 | 34718 | 0 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 13 | 0 | 5 | 0 | -| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 82 | 0 | 63 | 4 | -| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 4 | 0 | 4 | 0 | +| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 84 | 0 | 64 | 5 | +| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 8 | 0 | 7 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 27 | 0 | 14 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 3 | 0 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 255 | 1 | 195 | 15 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 259 | 1 | 199 | 15 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 12 | 0 | 12 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 1 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 39 | 0 | 39 | 0 | @@ -494,7 +500,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 2 | 0 | 1 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 8 | 0 | 8 | 0 | | | [@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) | - | 71 | 0 | 69 | 3 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 74 | 0 | 72 | 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/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 45 | 0 | 45 | 10 | @@ -520,15 +526,16 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 16 | 0 | 16 | 1 | | | [@elastic/security-detections-response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 107 | 0 | 104 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 0 | -| | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 63 | 1 | 63 | 0 | +| | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 65 | 0 | 65 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 16 | 0 | 8 | 0 | +| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 14 | 0 | 14 | 6 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 50 | 0 | 47 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 29 | 0 | 23 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 2 | 0 | 0 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 56 | 1 | 41 | 1 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 95 | 0 | 72 | 7 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 341 | 1 | 337 | 32 | -| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 87 | 0 | 76 | 1 | +| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 89 | 0 | 78 | 1 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 104 | 0 | 93 | 1 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 17 | 0 | 12 | 7 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 15 | 0 | 7 | 0 | @@ -587,27 +594,29 @@ 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) | - | 9 | 0 | 3 | 0 | -| | [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) | - | 133 | 0 | 130 | 0 | +| | [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) | - | 132 | 0 | 129 | 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 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 41 | 2 | 21 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 5 | 1 | -| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 282 | 4 | 238 | 12 | +| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 289 | 4 | 242 | 12 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 137 | 5 | 105 | 2 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 1 | 0 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 15 | 0 | 14 | 0 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 17 | 0 | 16 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 72 | 0 | 55 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 39 | 0 | 25 | 1 | | | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | - | 86 | 0 | 86 | 1 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 49 | 0 | 35 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 47 | 0 | 38 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 7 | 0 | 6 | 0 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list and field stats which can be integrated into apps | 306 | 0 | 277 | 9 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the unified data table which can be integrated into apps | 88 | 0 | 39 | 1 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 10 | 0 | 7 | 6 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list and field stats which can be integrated into apps | 302 | 0 | 275 | 9 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 4 | 0 | 0 | 0 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | - | 3 | 0 | 2 | 1 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 80 | 0 | 21 | 2 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 36 | 0 | 15 | 1 | +| | [@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) | - | 155 | 0 | 151 | 3 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 81ffb9b601f37..ecaa947603336 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.devdocs.json b/api_docs/profiling.devdocs.json index c6b864a1e228a..1b57fc843050b 100644 --- a/api_docs/profiling.devdocs.json +++ b/api_docs/profiling.devdocs.json @@ -185,39 +185,6 @@ "common": { "classes": [], "functions": [ - { - "parentPluginId": "profiling", - "id": "def-common.fromMapToRecord", - "type": "Function", - "tags": [], - "label": "fromMapToRecord", - "description": [], - "signature": [ - "(m: Map) => Record" - ], - "path": "x-pack/plugins/profiling/common/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "profiling", - "id": "def-common.fromMapToRecord.$1", - "type": "Object", - "tags": [], - "label": "m", - "description": [], - "signature": [ - "Map" - ], - "path": "x-pack/plugins/profiling/common/index.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "profiling", "id": "def-common.getRoutePaths", diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index fc5c13abdbba1..098608aaf23d5 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling- | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 19 | 1 | 19 | 3 | +| 17 | 1 | 17 | 3 | ## Client diff --git a/api_docs/profiling_data_access.devdocs.json b/api_docs/profiling_data_access.devdocs.json new file mode 100644 index 0000000000000..3528e7e26c101 --- /dev/null +++ b/api_docs/profiling_data_access.devdocs.json @@ -0,0 +1,76 @@ +{ + "id": "profilingDataAccess", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "profilingDataAccess", + "id": "def-server.ProfilingConfig", + "type": "Type", + "tags": [], + "label": "ProfilingConfig", + "description": [], + "signature": [ + "{ readonly elasticsearch?: Readonly<{} & { username: string; hosts: string; password: string; }> | undefined; }" + ], + "path": "x-pack/plugins/profiling_data_access/server/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "profilingDataAccess", + "id": "def-server.ProfilingDataAccessPluginStart", + "type": "Type", + "tags": [], + "label": "ProfilingDataAccessPluginStart", + "description": [], + "signature": [ + "{ services: { fetchFlamechartData: ({ esClient, rangeFrom, rangeTo, kuery }: FetchFlamechartParams) => Promise<", + "BaseFlameGraph", + ">; }; }" + ], + "path": "x-pack/plugins/profiling_data_access/server/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [], + "start": { + "parentPluginId": "profilingDataAccess", + "id": "def-server.ProfilingDataAccessPluginSetup", + "type": "Type", + "tags": [], + "label": "ProfilingDataAccessPluginSetup", + "description": [], + "signature": [ + "void" + ], + "path": "x-pack/plugins/profiling_data_access/server/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "lifecycle": "start", + "initialIsOpen": true + } + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx new file mode 100644 index 0000000000000..81490852f2548 --- /dev/null +++ b/api_docs/profiling_data_access.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: kibProfilingDataAccessPluginApi +slug: /kibana-dev-docs/api/profilingDataAccess +title: "profilingDataAccess" +image: https://source.unsplash.com/400x175/?github +description: API docs for the profilingDataAccess plugin +date: 2023-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] +--- +import profilingDataAccessObj from './profiling_data_access.devdocs.json'; + + + +Contact [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 3 | 0 | 3 | 1 | + +## Server + +### Start + + +### Consts, variables and types + + diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 2954c85fadc67..0ccfc6e5c1117 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 42ce63a81cecb..aa5afc089a631 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index bf42590dd0b5a..fbee8c197f306 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-08-25 +date: 2023-09-04 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 5becb8288089d..d21e3951f5f0d 100644 --- a/api_docs/rule_registry.devdocs.json +++ b/api_docs/rule_registry.devdocs.json @@ -891,6 +891,22 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "ruleRegistry", + "id": "def-server.RuleDataClient.isUsingDataStreams", + "type": "Function", + "tags": [], + "label": "isUsingDataStreams", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "x-pack/plugins/rule_registry/server/rule_data_client/rule_data_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "ruleRegistry", "id": "def-server.RuleDataClient.getReader", @@ -1719,7 +1735,7 @@ "section": "def-common.RuleTypeState", "text": "RuleTypeState" }, - " = never, InstanceState extends { [x: string]: unknown; } = never, InstanceContext extends { [x: string]: unknown; } = never, ActionGroupIds extends string = never>(wrappedExecutor: ", + " = never, InstanceState extends Record = never, InstanceContext extends { [x: string]: unknown; } = never, ActionGroupIds extends string = never>(wrappedExecutor: ", { "pluginId": "ruleRegistry", "scope": "server", @@ -1844,7 +1860,7 @@ "section": "def-common.RuleTypeParams", "text": "RuleTypeParams" }, - ", TAlertInstanceState extends { [x: string]: unknown; }, TAlertInstanceContext extends { [x: string]: unknown; }, TActionGroupIds extends string, TServices extends ", + ", TAlertInstanceState extends Record, TAlertInstanceContext extends { [x: string]: unknown; }, TActionGroupIds extends string, TServices extends ", { "pluginId": "ruleRegistry", "scope": "server", @@ -1987,7 +2003,7 @@ "section": "def-server.RuleExecutorOptions", "text": "RuleExecutorOptions" }, - ") => Promise<{ state: TState; }>; id: string; name: string; producer: string; validate: { params: ", + ", { [x: string]: unknown; }, \"default\", never>) => Promise<{ state: TState; }>; id: string; name: string; producer: string; validate: { params: ", "RuleTypeParamsValidator", "; }; cancelAlertsOnRuleTimeout?: boolean | undefined; alerts?: ", { @@ -2542,6 +2558,22 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "ruleRegistry", + "id": "def-server.IRuleDataClient.isUsingDataStreams", + "type": "Function", + "tags": [], + "label": "isUsingDataStreams", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "x-pack/plugins/rule_registry/server/rule_data_client/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "ruleRegistry", "id": "def-server.IRuleDataClient.getReader", @@ -3741,6 +3773,17 @@ "path": "x-pack/plugins/rule_registry/server/rule_data_client/rule_data_client.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-server.RuleDataClientConstructorOptions.isUsingDataStreams", + "type": "boolean", + "tags": [], + "label": "isUsingDataStreams", + "description": [], + "path": "x-pack/plugins/rule_registry/server/rule_data_client/rule_data_client.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -3791,7 +3834,7 @@ "section": "def-server.RuleType", "text": "RuleType" }, - ", \"executor\"> & { executor: ", + ", TAlertInstanceContext, string, string, never>, \"executor\"> & { executor: ", "AlertTypeExecutor", "; }" ], @@ -3856,7 +3899,7 @@ "section": "def-server.RuleType", "text": "RuleType" }, - "" + ", { [x: string]: unknown; }, \"default\", never, never>" ], "path": "x-pack/plugins/rule_registry/server/utils/persistence_types.ts", "deprecated": false, @@ -4174,7 +4217,7 @@ "section": "def-server.RuleType", "text": "RuleType" }, - ", \"executor\"> & { executor: (options: ", + ", TInstanceContext, TActionGroupIds, never, never>, \"executor\"> & { executor: (options: ", { "pluginId": "alerting", "scope": "server", @@ -4182,7 +4225,7 @@ "section": "def-server.RuleExecutorOptions", "text": "RuleExecutorOptions" }, - ", TInstanceContext, ", { "pluginId": "alerting", "scope": "common", @@ -4519,7 +4562,7 @@ "section": "def-common.RuleTypeParams", "text": "RuleTypeParams" }, - ", TAlertInstanceState extends { [x: string]: unknown; }, TAlertInstanceContext extends { [x: string]: unknown; }, TActionGroupIds extends string, TServices extends ", + ", TAlertInstanceState extends Record, TAlertInstanceContext extends { [x: string]: unknown; }, TActionGroupIds extends string, TServices extends ", { "pluginId": "ruleRegistry", "scope": "server", diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 46710e047480e..7d2698eedb107 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.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 | |-------------------|-----------|------------------------|-----------------| -| 264 | 0 | 235 | 14 | +| 267 | 0 | 238 | 14 | ## Server diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index de8a5f6d53d66..65589a9edc53e 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-08-25 +date: 2023-09-04 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 2ed017981c9f2..bc586f9346b8b 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-08-25 +date: 2023-09-04 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 48c4cec4075d7..90253b0a28e42 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index b033c3a53d425..cf51e4fd5f050 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-08-25 +date: 2023-09-04 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 7d5dc34f1d02d..1b1df37b6fea0 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-08-25 +date: 2023-09-04 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 47368bbfdadc5..efa013facd486 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-08-25 +date: 2023-09-04 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 241ffb062cc55..a54596f42a50a 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-08-25 +date: 2023-09-04 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 22c5c2a4408a8..a62c992300f18 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 8948dd6063c0a..0c17d6db807ca 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.devdocs.json b/api_docs/security.devdocs.json index f948514fa2fae..cb7f0176a308f 100644 --- a/api_docs/security.devdocs.json +++ b/api_docs/security.devdocs.json @@ -3210,10 +3210,6 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/annotations.ts" }, - { - "plugin": "logstash", - "path": "x-pack/plugins/logstash/server/routes/pipeline/save.ts" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/request_context_factory.ts" @@ -3238,6 +3234,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts" }, + { + "plugin": "logstash", + "path": "x-pack/plugins/logstash/server/routes/pipeline/save.ts" + }, { "plugin": "cloudChat", "path": "x-pack/plugins/cloud_integrations/cloud_chat/server/routes/chat.ts" @@ -3278,6 +3278,10 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/saved_objects/initialization/initialization.ts" }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/server/request_handler_context.ts" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/server/saved_objects/sync_task.ts" @@ -3290,10 +3294,6 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/plugin.ts" }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/server/request_handler_context.ts" - }, { "plugin": "enterpriseSearch", "path": "x-pack/plugins/enterprise_search/server/lib/check_access.ts" diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 1b9c037ce3c43..9943812818ff8 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index 06c2a37f3aa10..bda1742a17c6d 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -101,7 +101,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly detectionsCoverageOverview: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; readonly protectionUpdatesEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/plugin.tsx", "deprecated": false, @@ -480,7 +480,7 @@ "\nExperimental flag needed to enable the link" ], "signature": [ - "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"alertDetailsPageEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"alertsPageFiltersEnabled\" | \"newUserDetailsFlyout\" | \"detectionsCoverageOverview\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"discoverInTimeline\" | undefined" + "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"alertDetailsPageEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"alertsPageFiltersEnabled\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"discoverInTimeline\" | \"protectionUpdatesEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -560,7 +560,7 @@ "\nExperimental flag needed to disable the link. Opposite of experimentalKey" ], "signature": [ - "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"alertDetailsPageEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"alertsPageFiltersEnabled\" | \"newUserDetailsFlyout\" | \"detectionsCoverageOverview\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"discoverInTimeline\" | undefined" + "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"alertDetailsPageEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"alertsPageFiltersEnabled\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"discoverInTimeline\" | \"protectionUpdatesEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -1845,6 +1845,38 @@ ], "returnComment": [] }, + { + "parentPluginId": "securitySolution", + "id": "def-public.PluginStart.setIsILMAvailable", + "type": "Function", + "tags": [], + "label": "setIsILMAvailable", + "description": [], + "signature": [ + "(isILMAvailable: boolean) => void" + ], + "path": "x-pack/plugins/security_solution/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "securitySolution", + "id": "def-public.PluginStart.setIsILMAvailable.$1", + "type": "boolean", + "tags": [], + "label": "isILMAvailable", + "description": [], + "signature": [ + "boolean" + ], + "path": "x-pack/plugins/security_solution/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "securitySolution", "id": "def-public.PluginStart.setIsSidebarEnabled", @@ -2760,22 +2792,16 @@ "children": [ { "parentPluginId": "securitySolution", - "id": "def-server.SecuritySolutionPluginSetup.setAppFeatures", + "id": "def-server.SecuritySolutionPluginSetup.setAppFeaturesConfigurator", "type": "Function", "tags": [], - "label": "setAppFeatures", + "label": "setAppFeaturesConfigurator", "description": [ - "\nSets the app features that are available to the Security Solution" + "\nSets the configurations for app features that are available to the Security Solution" ], "signature": [ - "(appFeatureKeys: ", - { - "pluginId": "securitySolution", - "scope": "common", - "docId": "kibSecuritySolutionPluginApi", - "section": "def-common.AppFeatureKeys", - "text": "AppFeatureKeys" - }, + "(configurator: ", + "AppFeaturesConfigurator", ") => void" ], "path": "x-pack/plugins/security_solution/server/plugin_contract.ts", @@ -2785,22 +2811,15 @@ "children": [ { "parentPluginId": "securitySolution", - "id": "def-server.SecuritySolutionPluginSetup.setAppFeatures.$1", - "type": "Array", + "id": "def-server.SecuritySolutionPluginSetup.setAppFeaturesConfigurator.$1", + "type": "Object", "tags": [], - "label": "appFeatureKeys", + "label": "configurator", "description": [], "signature": [ - { - "pluginId": "securitySolution", - "scope": "common", - "docId": "kibSecuritySolutionPluginApi", - "section": "def-common.AppFeatureKey", - "text": "AppFeatureKey" - }, - "[]" + "AppFeaturesConfigurator" ], - "path": "x-pack/plugins/security_solution/server/lib/app_features/app_features.ts", + "path": "x-pack/plugins/security_solution/server/lib/app_features_service/app_features_service.ts", "deprecated": false, "trackAdoption": false } @@ -2906,47 +2925,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "securitySolution", - "id": "def-common.AppFeatureKey", - "type": "Type", - "tags": [], - "label": "AppFeatureKey", - "description": [], - "signature": [ - "AppFeatureSecurityKey", - " | ", - "AppFeatureCasesKey", - " | ", - "AppFeatureAssistantKey" - ], - "path": "x-pack/plugins/security_solution/common/types/app_features.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-common.AppFeatureKeys", - "type": "Type", - "tags": [], - "label": "AppFeatureKeys", - "description": [], - "signature": [ - { - "pluginId": "securitySolution", - "scope": "common", - "docId": "kibSecuritySolutionPluginApi", - "section": "def-common.AppFeatureKey", - "text": "AppFeatureKey" - }, - "[]" - ], - "path": "x-pack/plugins/security_solution/common/types/app_features.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "securitySolution", "id": "def-common.CASES_FEATURE_ID", @@ -2987,7 +2965,7 @@ "label": "ExperimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly detectionsCoverageOverview: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; readonly protectionUpdatesEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, @@ -3026,27 +3004,6 @@ } ], "objects": [ - { - "parentPluginId": "securitySolution", - "id": "def-common.ALL_APP_FEATURE_KEYS", - "type": "Object", - "tags": [], - "label": "ALL_APP_FEATURE_KEYS", - "description": [], - "signature": [ - "readonly (", - "AppFeatureSecurityKey", - " | ", - "AppFeatureCasesKey", - ".casesConnectors | ", - "AppFeatureAssistantKey", - ".assistant)[]" - ], - "path": "x-pack/plugins/security_solution/common/types/app_features.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "securitySolution", "id": "def-common.allowedExperimentalValues", @@ -3057,68 +3014,12 @@ "\nA list of allowed values that can be used in `xpack.securitySolution.enableExperimental`.\nThis object is then used to validate and parse the value entered." ], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly detectionsCoverageOverview: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly discoverInTimeline: boolean; readonly protectionUpdatesEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-common.AppFeatureKey", - "type": "Object", - "tags": [], - "label": "AppFeatureKey", - "description": [], - "path": "x-pack/plugins/security_solution/common/types/app_features.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "securitySolution", - "id": "def-common.AppFeatureKey.Unnamed", - "type": "Any", - "tags": [], - "label": "Unnamed", - "description": [], - "signature": [ - "any" - ], - "path": "x-pack/plugins/security_solution/common/types/app_features.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-common.AppFeatureKey.Unnamed", - "type": "Any", - "tags": [], - "label": "Unnamed", - "description": [], - "signature": [ - "any" - ], - "path": "x-pack/plugins/security_solution/common/types/app_features.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-common.AppFeatureKey.Unnamed", - "type": "Any", - "tags": [], - "label": "Unnamed", - "description": [], - "signature": [ - "any" - ], - "path": "x-pack/plugins/security_solution/common/types/app_features.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false } ] } diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 646262b37394e..d2c47afbde459 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/secur | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 175 | 3 | 109 | 34 | +| 170 | 0 | 104 | 32 | ## Client diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index 24c320bb97468..b7f07cfa02f71 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-08-25 +date: 2023-09-04 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 3a2e09c390759..85e2b206262e5 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-08-25 +date: 2023-09-04 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 d68901ea0c0f7..d3e8f8102ff8e 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-08-25 +date: 2023-09-04 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 1987d17a2c900..2c0835291b96c 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-08-25 +date: 2023-09-04 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 5c1d16722bbcf..512e5d7f50b02 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-08-25 +date: 2023-09-04 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 22df76f7b3893..ad8cfcd6b086e 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-08-25 +date: 2023-09-04 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 b99e543ef3362..2ba24457e986c 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-08-25 +date: 2023-09-04 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 7f02eaea405d0..a551a36b8dadd 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-08-25 +date: 2023-09-04 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 758bae39e5095..b5829c51da0e4 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-08-25 +date: 2023-09-04 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 059af7d3752bf..a533654133b9c 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-08-25 +date: 2023-09-04 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 8bb7c1b781dc2..cb35b02c0c9f2 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index db42b4af1f228..4ac2d1b7e45da 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index d80a29ac659e3..bbd19b33c99c5 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-08-25 +date: 2023-09-04 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 b28c18ff3ba2c..214d59c2ef888 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-08-25 +date: 2023-09-04 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 688f7a4d4c8e8..ff914617ea2c9 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-08-25 +date: 2023-09-04 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 1f0fbe90cd7d1..f2e82d110984d 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/text_based_languages.devdocs.json b/api_docs/text_based_languages.devdocs.json index e5f1b90b12a78..85e21f93ca908 100644 --- a/api_docs/text_based_languages.devdocs.json +++ b/api_docs/text_based_languages.devdocs.json @@ -210,6 +210,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "textBasedLanguages", + "id": "def-public.TextBasedLanguagesEditorProps.warning", + "type": "string", + "tags": [], + "label": "warning", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-text-based-editor/src/text_based_languages_editor.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "textBasedLanguages", "id": "def-public.TextBasedLanguagesEditorProps.isDisabled", @@ -251,6 +265,20 @@ "path": "packages/kbn-text-based-editor/src/text_based_languages_editor.tsx", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "textBasedLanguages", + "id": "def-public.TextBasedLanguagesEditorProps.hideMinimizeButton", + "type": "CompoundType", + "tags": [], + "label": "hideMinimizeButton", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-text-based-editor/src/text_based_languages_editor.tsx", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/text_based_languages.mdx b/api_docs/text_based_languages.mdx index 96cf8bcd39fe5..3aa599a10e74c 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'textBasedLanguages'] --- import textBasedLanguagesObj from './text_based_languages.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 | |-------------------|-----------|------------------------|-----------------| -| 17 | 0 | 17 | 0 | +| 19 | 0 | 19 | 0 | ## Client diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 0b42ac72efef6..de13a428cb962 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.devdocs.json b/api_docs/timelines.devdocs.json index 747cc36b3cd4b..a6c77777588d2 100644 --- a/api_docs/timelines.devdocs.json +++ b/api_docs/timelines.devdocs.json @@ -1377,30 +1377,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts" @@ -1437,6 +1413,30 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/components/event_details/cti_details/enrichment_summary.tsx" }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx" @@ -4273,34 +4273,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/index.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/index.tsx" - }, - { - "plugin": "@kbn/securitysolution-data-table", - "path": "x-pack/packages/security-solution/data_table/components/data_table/index.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts" @@ -4453,6 +4425,34 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/containers/source/mock.ts" }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/column_headers/helpers.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/index.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/index.tsx" + }, + { + "plugin": "@kbn/securitysolution-data-table", + "path": "x-pack/packages/security-solution/data_table/components/data_table/index.tsx" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/store/sourcerer/model.ts" @@ -4591,119 +4591,119 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/empty.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/overview/index.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/empty.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/overview/index.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_source_event.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_source_event.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_session.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_session.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/insights.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/insights.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/overview/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/overview/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_source_event.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_source_event.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_session.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_session.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/insights.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/insights/insights.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx" + "path": "x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/empty.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/empty.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx" + "path": "x-pack/plugins/security_solution/public/timelines/components/side_panel/index.tsx" }, { "plugin": "securitySolution", @@ -4725,14 +4725,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/components/drag_and_drop/drag_drop_context_wrapper.tsx" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/flyout/right/context.tsx" @@ -4751,11 +4743,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/right/hooks/use_prevalence.tsx" + "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/flyout/right/hooks/use_prevalence.tsx" + "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" }, { "plugin": "@kbn/securitysolution-data-table", diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 9bd1db7a18fac..ec62ba8e5a610 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-08-25 +date: 2023-09-04 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 2b2c7b71e8947..1760914e5845f 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index e215219abfae9..d5190a744a96e 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index ae3d2c419aed2..de2d1fdb7bd39 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-08-25 +date: 2023-09-04 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 6fd6835cb5a40..3a09c11478bf9 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.devdocs.json b/api_docs/unified_doc_viewer.devdocs.json new file mode 100644 index 0000000000000..eb3609aa71e6d --- /dev/null +++ b/api_docs/unified_doc_viewer.devdocs.json @@ -0,0 +1,263 @@ +{ + "id": "unifiedDocViewer", + "client": { + "classes": [], + "functions": [ + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.JsonCodeEditor", + "type": "Function", + "tags": [], + "label": "JsonCodeEditor", + "description": [], + "signature": [ + "React.ForwardRefExoticComponent<", + "JsonCodeEditorProps", + " & React.RefAttributes<{}>>" + ], + "path": "src/plugins/unified_doc_viewer/public/index.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.JsonCodeEditor.$1", + "type": "Uncategorized", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.UnifiedDocViewer", + "type": "Function", + "tags": [], + "label": "UnifiedDocViewer", + "description": [], + "signature": [ + "React.ForwardRefExoticComponent<", + "DocViewRenderProps", + " & React.RefAttributes<{}>>" + ], + "path": "src/plugins/unified_doc_viewer/public/index.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.UnifiedDocViewer.$1", + "type": "Uncategorized", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.useEsDocSearch", + "type": "Function", + "tags": [], + "label": "useEsDocSearch", + "description": [ + "\nCustom react hook for querying a single doc in ElasticSearch" + ], + "signature": [ + "({\n id,\n index,\n dataView,\n requestSource,\n textBasedHits,\n}: ", + "EsDocSearchProps", + ") => [", + { + "pluginId": "@kbn/unified-doc-viewer", + "scope": "common", + "docId": "kibKbnUnifiedDocViewerPluginApi", + "section": "def-common.ElasticRequestState", + "text": "ElasticRequestState" + }, + ", ", + "DataTableRecord", + " | null, () => void]" + ], + "path": "src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.useEsDocSearch.$1", + "type": "Object", + "tags": [], + "label": "{\n id,\n index,\n dataView,\n requestSource,\n textBasedHits,\n}", + "description": [], + "signature": [ + "EsDocSearchProps" + ], + "path": "src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.useUnifiedDocViewerServices", + "type": "Function", + "tags": [], + "label": "useUnifiedDocViewerServices", + "description": [], + "signature": [ + "() => ", + "UnifiedDocViewerServices" + ], + "path": "src/plugins/unified_doc_viewer/public/hooks/use_doc_viewer_services.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [], + "setup": { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.UnifiedDocViewerSetup", + "type": "Interface", + "tags": [], + "label": "UnifiedDocViewerSetup", + "description": [], + "path": "src/plugins/unified_doc_viewer/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.UnifiedDocViewerSetup.addDocView", + "type": "Function", + "tags": [], + "label": "addDocView", + "description": [], + "signature": [ + "(docViewRaw: ", + "DocViewInput", + " | ", + "DocViewInputFn", + ") => void" + ], + "path": "src/plugins/unified_doc_viewer/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.UnifiedDocViewerSetup.addDocView.$1", + "type": "CompoundType", + "tags": [], + "label": "docViewRaw", + "description": [], + "signature": [ + "DocViewInput", + " | ", + "DocViewInputFn" + ], + "path": "packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "lifecycle": "setup", + "initialIsOpen": true + }, + "start": { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.UnifiedDocViewerStart", + "type": "Interface", + "tags": [], + "label": "UnifiedDocViewerStart", + "description": [], + "path": "src/plugins/unified_doc_viewer/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.UnifiedDocViewerStart.getDocViews", + "type": "Function", + "tags": [], + "label": "getDocViews", + "description": [], + "signature": [ + "(hit: ", + "DataTableRecord", + ") => ", + "DocView", + "[]" + ], + "path": "src/plugins/unified_doc_viewer/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "unifiedDocViewer", + "id": "def-public.UnifiedDocViewerStart.getDocViews.$1", + "type": "Object", + "tags": [], + "label": "hit", + "description": [], + "signature": [ + "DataTableRecord" + ], + "path": "packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "lifecycle": "start", + "initialIsOpen": true + } + }, + "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/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx new file mode 100644 index 0000000000000..571d25c7d740a --- /dev/null +++ b/api_docs/unified_doc_viewer.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibUnifiedDocViewerPluginApi +slug: /kibana-dev-docs/api/unifiedDocViewer +title: "unifiedDocViewer" +image: https://source.unsplash.com/400x175/?github +description: API docs for the unifiedDocViewer plugin +date: 2023-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] +--- +import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; + +This plugin contains services reliant on the plugin lifecycle for the unified doc viewer component (see @kbn/unified-doc-viewer). + +Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 13 | 0 | 10 | 3 | + +## Client + +### Setup + + +### Start + + +### Functions + + diff --git a/api_docs/unified_histogram.devdocs.json b/api_docs/unified_histogram.devdocs.json index 5b5b6d13ef809..afa74e73e7990 100644 --- a/api_docs/unified_histogram.devdocs.json +++ b/api_docs/unified_histogram.devdocs.json @@ -468,7 +468,7 @@ }, " | undefined; } & Pick<", "UnifiedHistogramLayoutProps", - ", \"children\" | \"className\" | \"query\" | \"filters\" | \"columns\" | \"timeRange\" | \"dataView\" | \"services\" | \"relativeTimeRange\" | \"resizeRef\" | \"appendHitsCounter\"> & React.RefAttributes<", + ", \"children\" | \"className\" | \"query\" | \"filters\" | \"columns\" | \"onBrushEnd\" | \"disabledActions\" | \"timeRange\" | \"services\" | \"dataView\" | \"relativeTimeRange\" | \"resizeRef\" | \"appendHitsCounter\" | \"onFilter\" | \"withDefaultActions\"> & React.RefAttributes<", { "pluginId": "unifiedHistogram", "scope": "public", @@ -1178,7 +1178,7 @@ }, " | undefined; } & Pick<", "UnifiedHistogramLayoutProps", - ", \"children\" | \"className\" | \"query\" | \"filters\" | \"columns\" | \"timeRange\" | \"dataView\" | \"services\" | \"relativeTimeRange\" | \"resizeRef\" | \"appendHitsCounter\">" + ", \"children\" | \"className\" | \"query\" | \"filters\" | \"columns\" | \"onBrushEnd\" | \"disabledActions\" | \"timeRange\" | \"services\" | \"dataView\" | \"relativeTimeRange\" | \"resizeRef\" | \"appendHitsCounter\" | \"onFilter\" | \"withDefaultActions\">" ], "path": "src/plugins/unified_histogram/public/container/container.tsx", "deprecated": false, diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index b63fd550e8b19..69973dbca64eb 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.devdocs.json b/api_docs/unified_search.devdocs.json index a9e18958ae822..db79545b07381 100644 --- a/api_docs/unified_search.devdocs.json +++ b/api_docs/unified_search.devdocs.json @@ -3,6 +3,157 @@ "client": { "classes": [], "functions": [ + { + "parentPluginId": "unifiedSearch", + "id": "def-public.createFilterAction", + "type": "Function", + "tags": [], + "label": "createFilterAction", + "description": [], + "signature": [ + "(filterManager: ", + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataQueryPluginApi", + "section": "def-public.FilterManager", + "text": "FilterManager" + }, + ", timeFilter: ", + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataQueryPluginApi", + "section": "def-public.TimefilterContract", + "text": "TimefilterContract" + }, + ", theme: ", + { + "pluginId": "@kbn/core-theme-browser", + "scope": "common", + "docId": "kibKbnCoreThemeBrowserPluginApi", + "section": "def-common.ThemeServiceSetup", + "text": "ThemeServiceSetup" + }, + ", id: string, type: string) => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.ActionDefinition", + "text": "ActionDefinition" + }, + "<", + { + "pluginId": "unifiedSearch", + "scope": "public", + "docId": "kibUnifiedSearchPluginApi", + "section": "def-public.ApplyGlobalFilterActionContext", + "text": "ApplyGlobalFilterActionContext" + }, + ">" + ], + "path": "src/plugins/unified_search/public/actions/apply_filter_action.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedSearch", + "id": "def-public.createFilterAction.$1", + "type": "Object", + "tags": [], + "label": "filterManager", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataQueryPluginApi", + "section": "def-public.FilterManager", + "text": "FilterManager" + } + ], + "path": "src/plugins/unified_search/public/actions/apply_filter_action.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedSearch", + "id": "def-public.createFilterAction.$2", + "type": "Object", + "tags": [], + "label": "timeFilter", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataQueryPluginApi", + "section": "def-public.TimefilterContract", + "text": "TimefilterContract" + } + ], + "path": "src/plugins/unified_search/public/actions/apply_filter_action.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedSearch", + "id": "def-public.createFilterAction.$3", + "type": "Object", + "tags": [], + "label": "theme", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-theme-browser", + "scope": "common", + "docId": "kibKbnCoreThemeBrowserPluginApi", + "section": "def-common.ThemeServiceSetup", + "text": "ThemeServiceSetup" + } + ], + "path": "src/plugins/unified_search/public/actions/apply_filter_action.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedSearch", + "id": "def-public.createFilterAction.$4", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/unified_search/public/actions/apply_filter_action.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedSearch", + "id": "def-public.createFilterAction.$5", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/unified_search/public/actions/apply_filter_action.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "unifiedSearch", "id": "def-public.createSearchBar", @@ -275,7 +426,7 @@ "section": "def-public.FilterItemsProps", "text": "FilterItemsProps" }, - ", \"filters\" | \"indexPatterns\" | \"readOnly\" | \"filtersForSuggestions\" | \"suggestionsAbstraction\" | \"onFiltersUpdated\" | \"hiddenPanelOptions\" | \"timeRangeForSuggestionsOverride\"> & React.RefAttributes & React.RefAttributes, any, any>>) => JSX.Element" + ", \"filters\" | \"indexPatterns\" | \"filtersForSuggestions\" | \"suggestionsAbstraction\" | \"onFiltersUpdated\" | \"hiddenPanelOptions\" | \"readOnly\" | \"timeRangeForSuggestionsOverride\">, any, any>>) => JSX.Element" ], "path": "src/plugins/unified_search/public/filter_bar/index.tsx", "deprecated": false, @@ -305,7 +456,7 @@ "section": "def-public.FilterItemsProps", "text": "FilterItemsProps" }, - ", \"filters\" | \"indexPatterns\" | \"readOnly\" | \"filtersForSuggestions\" | \"suggestionsAbstraction\" | \"onFiltersUpdated\" | \"hiddenPanelOptions\" | \"timeRangeForSuggestionsOverride\"> & React.RefAttributes & React.RefAttributes, any, any>>" + ", \"filters\" | \"indexPatterns\" | \"filtersForSuggestions\" | \"suggestionsAbstraction\" | \"onFiltersUpdated\" | \"hiddenPanelOptions\" | \"readOnly\" | \"timeRangeForSuggestionsOverride\">, any, any>>" ], "path": "src/plugins/unified_search/public/filter_bar/index.tsx", "deprecated": false, @@ -550,7 +701,7 @@ "section": "def-public.DataViewPickerProps", "text": "DataViewPickerProps" }, - " | undefined; textBasedLanguageModeErrors?: Error[] | undefined; onTextBasedSavedAndExit?: (({ onSave }: ", + " | undefined; textBasedLanguageModeErrors?: Error[] | undefined; textBasedLanguageModeWarning?: string | undefined; onTextBasedSavedAndExit?: (({ onSave }: ", "OnSaveTextLanguageQueryProps", ") => void) | undefined; showSubmitButton?: boolean | undefined; submitButtonStyle?: \"full\" | \"auto\" | \"iconOnly\" | undefined; suggestionsSize?: ", "SuggestionsListSize", diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 3b901ba0a28bf..f357c8beb788e 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_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 | |-------------------|-----------|------------------------|-----------------| -| 142 | 2 | 104 | 22 | +| 148 | 2 | 110 | 22 | ## Client diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 0d15470f23da2..d647c437f3e23 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.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 | |-------------------|-----------|------------------------|-----------------| -| 142 | 2 | 104 | 22 | +| 148 | 2 | 110 | 22 | ## Client diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index 9d4640738bee9..26293283ce30b 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-08-25 +date: 2023-09-04 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 bbe42b8284cba..115e3a97f04e5 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.devdocs.json b/api_docs/usage_collection.devdocs.json index d3e9b42e13140..2def62795ca5f 100644 --- a/api_docs/usage_collection.devdocs.json +++ b/api_docs/usage_collection.devdocs.json @@ -1942,7 +1942,7 @@ "section": "def-server.MakeSchemaFrom", "text": "MakeSchemaFrom" }, - " | undefined; fetch: ", + " | undefined; fetch: ", { "pluginId": "usageCollection", "scope": "server", @@ -1981,9 +1981,9 @@ "signature": [ "{ [Key in keyof Required]: Required[Key] extends (infer U)[] ? { type: \"array\"; items: ", "RecursiveMakeSchemaFrom", - "; } : ", + "; } : ", "RecursiveMakeSchemaFrom", - "[Key]>; }" + "[Key], RequireMeta>; }" ], "path": "src/plugins/usage_collection/server/collector/types.ts", "deprecated": false, @@ -2025,7 +2025,7 @@ "section": "def-server.MakeSchemaFrom", "text": "MakeSchemaFrom" }, - " | undefined; fetch: ", + " | undefined; fetch: ", { "pluginId": "usageCollection", "scope": "server", @@ -2041,7 +2041,7 @@ "section": "def-server.MakeSchemaFrom", "text": "MakeSchemaFrom" }, - " | undefined; fetch: ", + " | undefined; fetch: ", { "pluginId": "usageCollection", "scope": "server", diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 35ca8ac3ec44a..20257c78f92dc 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-08-25 +date: 2023-09-04 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 c8ca9c0888b29..bc34b640cd0f2 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-08-25 +date: 2023-09-04 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 c61bb2591eba9..fd7fa07acbd47 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-08-25 +date: 2023-09-04 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 a0048c0eb17df..9de719a174d83 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-08-25 +date: 2023-09-04 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 81af7c7c1b06f..5496a85f6e8cb 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-08-25 +date: 2023-09-04 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 3caaa0a1403c2..5edba7017e4e3 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-08-25 +date: 2023-09-04 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 5f448058d7c09..dde81fe2992d5 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-08-25 +date: 2023-09-04 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 27a0ad6de6f52..4b0c6a3fc28e8 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-08-25 +date: 2023-09-04 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 ac14d2c13787f..0de2d846d05c1 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-08-25 +date: 2023-09-04 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 9f286a21331c3..f45bff62d331c 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-08-25 +date: 2023-09-04 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 37d1c461f3c27..079df61084cff 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-08-25 +date: 2023-09-04 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 46ae3968f0fdf..b861dea9de5dc 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.devdocs.json b/api_docs/visualizations.devdocs.json index 02291d78d807b..5b78f2be3fd99 100644 --- a/api_docs/visualizations.devdocs.json +++ b/api_docs/visualizations.devdocs.json @@ -2249,7 +2249,7 @@ "section": "def-common.DatatableRow", "text": "DatatableRow" }, - "[]; }" + "[]; warning?: string | undefined; }" ], "path": "src/plugins/visualizations/common/utils/prepare_log_table.ts", "deprecated": false, @@ -8133,7 +8133,7 @@ "section": "def-common.DatatableRow", "text": "DatatableRow" }, - "[]; }" + "[]; warning?: string | undefined; }" ], "path": "src/plugins/visualizations/common/utils/prepare_log_table.ts", "deprecated": false, diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index b2f645e13aea5..7d8cfe702d222 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-08-25 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/catalog-info.yaml b/catalog-info.yaml index d37b33eb0ebff..00637fb1a039b 100644 --- a/catalog-info.yaml +++ b/catalog-info.yaml @@ -123,4 +123,40 @@ spec: lifecycle: production system: control-plane +--- +apiVersion: backstage.io/v1alpha1 +kind: Resource +metadata: + name: kibana-serverless-release + description: Definition of the kibana release pipeline + links: + - title: Pipeline + url: https://buildkite.com/elastic/kibana-serverless-release +spec: + type: buildkite-pipeline + owner: group:kibana-operations + system: buildkite + implementation: + apiVersion: buildkite.elastic.dev/v1 + kind: Pipeline + metadata: + name: kibana-serverless-release + description: Pipeline that releases kibana by triggering the release flow through qa, staging, and production + spec: + repository: elastic/kibana + pipeline_file: ./.buildkite/pipelines/pipeline.kibana-serverless-release.yaml + provider_settings: + build_branches: false + build_pull_request_forks: false + build_tags: true + # https://regex101.com/r/tY52jo/1 + filter_condition: 'build.tag =~ /^deploy@\d+$/' + filter_enabled: true + teams: + kibana-operations: + access_level: MANAGE_BUILD_AND_READ + kibana-tech-leads: + access_level: MANAGE_BUILD_AND_READ + everyone: + access_level: READ_ONLY diff --git a/config/node.options b/config/node.options index d5799f2c2068a..abcb40a5c19d4 100644 --- a/config/node.options +++ b/config/node.options @@ -10,3 +10,6 @@ ## restore < Node 16 default DNS lookup behavior --dns-result-order=ipv4first + +## enable OpenSSL 3 legacy provider +--openssl-legacy-provider diff --git a/config/serverless.es.yml b/config/serverless.es.yml index 8ee07c718cce0..7a1da782855bd 100644 --- a/config/serverless.es.yml +++ b/config/serverless.es.yml @@ -32,3 +32,6 @@ telemetry.labels.serverless: search # Alerts config xpack.actions.enabledActionTypes: ['.email', '.index', '.slack', '.jira', '.webhook', '.teams'] + +# Customize empty page state for analytics apps +no_data_page.analyticsNoDataPageFlavor: 'serverless_search' diff --git a/config/serverless.oblt.yml b/config/serverless.oblt.yml index 44d26351b5380..5e6b9a58cbc35 100644 --- a/config/serverless.oblt.yml +++ b/config/serverless.oblt.yml @@ -10,7 +10,6 @@ xpack.serverless.observability.enabled: true ## Configure plugins xpack.infra.logs.app_target: discover -xpack.discoverLogExplorer.featureFlags.deepLinkVisible: true ## Set the home route uiSettings.overrides.defaultRoute: /app/observability/landing diff --git a/config/serverless.yml b/config/serverless.yml index e18049e8517c6..1349f71d019e6 100644 --- a/config/serverless.yml +++ b/config/serverless.yml @@ -13,11 +13,12 @@ xpack.cloud.base_url: "https://cloud.elastic.co" # Enable ZDT migration algorithm migrations.algorithm: zdt -# temporarily allow to run the migration on UI nodes -# until the controller is able to spawn the migrator job/pod +# Limit batch size to reduce possibility of failures. +# A longer migration time is acceptable due to the ZDT algorithm. +migrations.batchSize: 250 + migrations.zdt: metaPickupSyncDelaySec: 5 - runOnRoles: ['ui'] # Ess plugins xpack.securitySolutionEss.enabled: false @@ -86,6 +87,12 @@ console.autocompleteDefinitions.endpointsAvailability: serverless # Allow authentication via the Elasticsearch JWT realm with the `shared_secret` client authentication type. elasticsearch.requestHeadersWhitelist: ["authorization", "es-client-authentication"] +# Limit maxSockets to 800 as we do in ESS, which improves reliability under high loads. +elasticsearch.maxSockets: 800 + +# Enable dynamic config to be updated via the internal HTTP requests +coreApp.allowDynamicConfigOverrides: true + # Visualizations editors readonly settings vis_type_gauge.readOnly: true vis_type_heatmap.readOnly: true @@ -112,6 +119,11 @@ xpack.alerting.rules.run.ruleTypeOverrides: xpack.alerting.rules.minimumScheduleInterval.enforce: true xpack.actions.run.maxAttempts: 10 +# Disables ESQL in advanced settings (hides it from the UI) +uiSettings: + overrides: + discover:enableESQL: false + # Task Manager xpack.task_manager.allow_reading_invalid_state: false diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index 898597eabce5d..5e3394b9add9f 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -10,6 +10,7 @@ Review important information about the {kib} 8.x releases. +* <> * <> * <> * <> @@ -46,6 +47,269 @@ Review important information about the {kib} 8.x releases. * <> -- +[[release-notes-8.10.0]] +== {kib} 8.10.0 + +coming::[8.10.0] + +For information about the {kib} 8.10.0 release, review the following information. + +[float] +[[breaking-changes-8.10.0]] +=== Breaking changes + +Breaking changes can prevent your application from optimal operation and performance. +Before you upgrade to 8.10.0, review the breaking changes, then mitigate the impact to your application. + +[discrete] +[[breaking-162665]] +.New summary search capabilities +[%collapsible] +==== +*Details* + +New summary search capabilities introduce breaking changes in various places, and we have decided to not handle backward compatibility: + +* SLO find API body parameters have changed +* The index mapping used by the rollup data has changed, and we have added a summary index that becomes the new source of truth for search +* The rollup transform have been updated, but existing SLO with their transform won't be updated. + +If some SLOs have been installed in a prior version at 8.10, the user will need to remove them manually from the UI, or by deleting the Saved Object and the associated Transform. +==== + +[discrete] +[[breaking-162506]] +.Get case metrics APIs now internal +[%collapsible] +==== +*Details* + +The get case metrics APIs are now internal. For more information, refer to ({kibana-pull}162506[#162506]). +==== + +[discrete] +[[breaking-162492]] +.Case limits +[%collapsible] +==== +*Details* + +Limits are now imposed on the number of objects cases can process or the amount of data those objects can store. +//// +For example: +* Updating a case comment is now included in the 10000 user actions restriction. ({kibana-pull}163150[#163150]) +* Updating a case now fails if the operation makes it reach more than 10000 user actions. ({kibana-pull}161848[#161848]) +* The total number of characters per comment is limited to 30000. ({kibana-pull}161357[#161357]) +* The getConnectors API now limits the number of supported connectors returned to 1000. ({kibana-pull}161282[#161282]) +* There are new limits and restrictions when retrieving cases. ({kibana-pull}162411[#162411]), ({kibana-pull}162245[#162245]), ({kibana-pull}161111[#161111]), ({kibana-pull}160705[#160705]) +* A case can now only have 100 external references and persistable state(excluding files) attachments combined. ({kibana-pull}162071[#162071]). +* New limits on titles, descriptions, tags and category. ({kibana-pull}160844[#160844]). +* The maximum number of cases that can be updated simultaneously is now 100. The minimum is 1. ({kibana-pull}161076[#161076]). +* The Delete cases API now limits the number of cases to be deleted to 100.({kibana-pull}160846[#160846]). +//// +For the full list, refer to {kib-issue}146945[#146945]. +==== + +[discrete] +[[breaking-159041]] +.`addProcessorDefinition` is removed +[%collapsible] +==== +*Details* + +The function `addProcessorDefinition` is removed from the Console plugin start contract (server side). For more information, refer to ({kibana-pull}159041[#159041]). +==== + +[float] +[[deprecations-8.10.0]] +=== Deprecations + +The following functionality is deprecated in 8.10.0, and will be removed in 9.0.0. +Deprecated functionality does not have an immediate impact on your application, but we strongly recommend +you make the necessary updates after you upgrade to 8.10.0. + +[discrete] +[[deprecation-161136]] +.Action variables in the UI and in tests that were no longer used have been replaced +[%collapsible] +==== +*Details* + +The following rule action variables have been deprecated; use the recommended variables (in parentheses) instead: + +* alertActionGroup (alert.actionGroup) +* alertActionGroupName (alert.actionGroupName) +* alertActionSubgroup (alert.actionSubgroup) +* alertId (rule.id) +* alertInstanceId (alert.id) +* alertName (rule.name) +* params (rule.params) +* spaceId (rule.spaceId) +* tags (rule.tags) + +For more information, refer to ({kibana-pull}161136[#161136]). +==== + +[float] +[[features-8.10.0]] +=== Features +{kib} 8.10.0 adds the following new and notable features. + +Alerting:: +* Adds support for self-signed SSL certificate authentication in webhook connector ({kibana-pull}161894[#161894]). +* Allow runtime fields to be selected for {es} query rule type 'group by' or 'aggregate over' options ({kibana-pull}160319[#160319]). +APM:: +* Adds KQL filtering in APM rules ({kibana-pull}163825[#163825]). +* Make service group saved objects exportable ({kibana-pull}163569[#163569]). +* Added ability to manage Cross-Cluster API keys ({kibana-pull}162363[#162363]). +* Enable Trace Explorer by default ({kibana-pull}162308[#162308]). +* Adds error.grouping_name to group alerts in Error Count rule ({kibana-pull}161810[#161810]). +* Adds query to check for overflow bucket in service groups ({kibana-pull}159990[#159990]). +Elastic Security:: +For the Elastic Security 8.10.0 release information, refer to {security-guide}/release-notes.html[_Elastic Security Solution Release Notes_]. +Enterprise Search:: +For the Elastic Enterprise Search 8.10.0 release information, refer to {enterprise-search-ref}/changelog.html[_Elastic Enterprise Search Documentation Release notes_]. +Fleet:: +* Only enable secret storage once all fleet servers are above 8.10.0 ({kibana-pull}163627[#163627]). +* Kafka integration API ({kibana-pull}159110[#159110]). +Machine Learning:: +* AIOps: Adds/edits change point charts embeddable from the Dashboard app ({kibana-pull}163694[#163694]). +* AIOps: Adds change point detection charts embeddable ({kibana-pull}162796[#162796]). +* Adds ability to deploy trained models for data frame analytics jobs ({kibana-pull}162537[#162537]). +* Adds map view for models in Trained Models and expands support for models in Analytics map ({kibana-pull}162443[#162443]). +* Adds new Data comparison view ({kibana-pull}161365[#161365]). +Management:: +* Added ability to create a remote cluster with the API key based security model ({kibana-pull}161836[#161836]). +* REST endpoint for swapping saved object references ({kibana-pull}157665[#157665]). +Maps:: +* Maps tracks layer now uses group by time series logic ({kibana-pull}159267[#159267]). +Observability:: +* SLO definition and computed values are now summarized periodically into a summary search index, allowing users to search by name, tags, SLO budgeting type or time window, and even by and sort by error budget consumed, error budget remaining, SLI value or status ({kibana-pull}162665[#162665]). +* Adds indicator to support histogram fields ({kibana-pull}161582[#161582]). + +For more information about the features introduced in 8.10.0, refer to <>. + +[[enhancements-and-bug-fixes-v8.10.0]] +=== Enhancements and bug fixes + +For detailed information about the 8.10.0 release, review the enhancements and bug fixes. + +[float] +[[enhancement-v8.10.0]] +=== Enhancements +Alerting:: +* Fixes the event log data stream to use Data stream lifecycle instead of Index Lifecycle Management. If you had previously customized the Kibana event log ILM policy, you should now update the lifecycle of the event log data stream itself. ({kibana-pull}163210[#163210]). +* KQL search bar for Rules page ({kibana-pull}158106[#158106]). +APM:: +* Lens function ({kibana-pull}163872[#163872]). +* Adds several function implementations to the AI Assistant ({kibana-pull}163764[#163764]). +* Feature controls ({kibana-pull}163232[#163232]). +* Added improved JVM runtime metrics dashboard ({kibana-pull}162460[#162460]). +* Move to new plugin, update design and use connectors ({kibana-pull}162243[#162243]). +* Adding endpoint to upload android map files ({kibana-pull}161252[#161252]). +* Navigate from the transaction details view into the Profiling ({kibana-pull}159686[#159686]). +Dashboard:: +* Change badge color in options list ({kibana-pull}161401[#161401]). +* Edit title, description, and tags from dashboard listing page ({kibana-pull}161399[#161399]). +* Editing toolbar update ({kibana-pull}154966[#154966]). +Discover:: +* Inline shard failures warnings ({kibana-pull}161271[#161271]). +* Improve shard error message formatting ({kibana-pull}161098[#161098]). +Elastic Security:: +For the Elastic Security 8.10.0 release information, refer to {security-guide}/release-notes.html[_Elastic Security Solution Release Notes_]. +Enterprise Search:: +For the Elastic Enterprise Search 8.10.0 release information, refer to {enterprise-search-ref}/changelog.html[_Elastic Enterprise Search Documentation Release notes_]. +Fleet:: +* Adds support for runtime fields ({kibana-pull}161129[#161129]). +Lens & Visualizations:: +* Migrate range slider to `EuiDualRange` and make styling consistent across all controls ({kibana-pull}162651[#162651]). +* Introduce new duration formatter in *Lens* ({kibana-pull}162246[#162246]). +* Create a filter with field:value when last value metric is used on a data table in *Lens* ({kibana-pull}160509[#160509]). +* Adds tooltip for partition and heatmap filtering ({kibana-pull}162716[#162716]). +Machine Learning:: +* Hides paging controls in anomaly swim lane if only one page is available ({kibana-pull}163931[#163931]). +* Adds a throughput description in the Trained Models Deployment stats table ({kibana-pull}163481[#163481]). +* Provides hints for empty fields in dropdown options in Anomaly detection & Transform creation wizards, Change point detection view ({kibana-pull}163371[#163371]). +* AIOps: Adds dip support to log rate analysis in ML AIOps Labs ({kibana-pull}163100[#163100]). +* AIOps: Improves table hovering for log rate analysis ({kibana-pull}162941[#162941]). +* AIOps: Adds dip support for log rate analysis in observability alert details page ({kibana-pull}162476[#162476]). +* Adds validation of field selected for log pattern analysis ({kibana-pull}162319[#162319]). +* AIOps: Renames Explain Log Rate Spikes to Log Rate Analysis ({kibana-pull}161764[#161764]). +* Adds new Data comparison view ({kibana-pull}161365[#161365]). +* Adds test UI for text expansion models ({kibana-pull}159150[#159150]). +* Adds update index mappings step to ML pipeline config workflow ({kibana-pull}163723[#163723]). +Management:: +* Adds multiple formats for geo_point fields and make geo conversion tools part of field_format/common/utils ({kibana-pull}147272[#147272]). +Maps:: +* Support time series split for top hits per entity source ({kibana-pull}161799[#161799]). +Observability:: +* Adds support for group by to SLO burn rate rule ({kibana-pull}163434[#163434]). +* Applying consistent design to Histogram and Custom Metric forms ({kibana-pull}162083[#162083]). +* Adds preview chart to custom metric indicator ({kibana-pull}161597[#161597]). +* Support filters for good/total custom metrics ({kibana-pull}161308[#161308]). +Reporting:: +* Increase max size bytes default to 250mb ({kibana-pull}161318[#161318]). +Security:: +* Change the default value of `session.idleTimeout` from 8 hours to 3 days ({kibana-pull}162313[#162313]). +* User roles displayed on the user profile page ({kibana-pull}161375[#161375]). +Uptime:: +* Implement private location run once ({kibana-pull}162582[#162582]). + +[float] +[[fixes-v8.10.0]] +=== Bug Fixes +APM:: +* Fixes styling and port issue with new onboarding ({kibana-pull}163922[#163922]). +* Fixes missing alert index issue ({kibana-pull}163600[#163600]). +* Fixes trace waterfall loading logic to handle empty scenarios ({kibana-pull}163397[#163397]). +* Fixes the action menu overlapping the 'Create custom link' flyout ({kibana-pull}162664[#162664]). +* Improve service groups error messages and validations ({kibana-pull}162556[#162556]). +* Fixes throwing appropriate error when user is missing necessary permission ({kibana-pull}162466[#162466]). +* Hide components when there is no support from agents ({kibana-pull}161970[#161970]). +* Fixes link to onboarding page in the Observability Onboarding plugin ({kibana-pull}161847[#161847]). +Dashboard:: +* Disables top navigation actions when cloning or overlay is showing ({kibana-pull}162091[#162091]). +Discover:: +* Fixes document failing to load when the ID contains a slash ({kibana-pull}160239[#160239]). +* Fixes NoData screen in alignment with Dashboard and Lends behavior ({kibana-pull}160747[#160747]). +Elastic Security:: +For the Elastic Security 8.10.0 release information, refer to {security-guide}/release-notes.html[_Elastic Security Solution Release Notes_]. +Enterprise Search:: +For the Elastic Enterprise Search 8.10.0 release information, refer to {enterprise-search-ref}/changelog.html[_Elastic Enterprise Search Documentation Release notes_]. +Fleet:: +* Only show agent dashboard links if there is more than one non-server agent and if the dashboards exist ({kibana-pull}164469[#164469]). +* Exclude Synthetics from per-policy-outputs ({kibana-pull}161949[#161949]). +* Fixing the path for hint templates for auto-discover ({kibana-pull}161075[#161075]). +Lens & Visualizations:: +* Fixes params._interval conversion to Lens formula ({kibana-pull}164150[#164150]). +* Fixes issues with field name that contains the `:` character in it in *Lens* ({kibana-pull}163626[#163626]). +* Fixes other request merge behavior when empty string key is retrieved ({kibana-pull}163187[#163187]). +* Fixes editing of multi values filters when adding a custom item ({kibana-pull}161940[#161940]). +* Allow setting custom colors to be collapsed by slices pie's multiple metrics in *Lens* ({kibana-pull}160592[#160592]). +* Fixes data table sorting for keyword values in *Lens* ({kibana-pull}160163[#160163]). +* Fixes override parameter when creating data views ({kibana-pull}160953[#160953]). +Logs:: +* Amend lazy imports in logs_shared plugin ({kibana-pull}164102[#164102]). +Machine Learning:: +* Fixes Trained models list crashes on browser refresh if not on page 1 ({kibana-pull}164163[#164163]). +* Fixes query bar not switching from KQL to Lucene and vice versa in Anomaly explorer ({kibana-pull}163625[#163625]). +* Data Frame Analytics creation wizard: ensures validation works correctly ({kibana-pull}163446[#163446]). +* Fixes capabilities polling in manage page ({kibana-pull}163399[#163399]). +* Fixes unhandled promise rejection from ML plugin ({kibana-pull}163129[#163129]). +* AIOps: Uses Kibana's http service instead of fetch and fixes throttling ({kibana-pull}162335[#162335]). +* Uses model supplied mask token for testing trained models ({kibana-pull}162168[#162168]). +Management:: +* Fixes how a bulk request body with variables are processed in Console ({kibana-pull}162745[#162745]). +* Improves a way of variable substitution and its documentation in Console ({kibana-pull}162382[#162382]). +* Transforms: Reduces rerenders and multiple fetches of source index on transform wizard load ({kibana-pull}160979[#160979]). +Maps:: +* Fixes Map layer preview blocks adding layer until all tiles are loaded ({kibana-pull}161994[#161994]). +Monitoring:: +* Rewrite CPU usage rule to improve accuracy ({kibana-pull}159351[#159351]). +Observability:: +* Fixes email connector rule URL ({kibana-pull}162954[#162954]). +* Disable the 'View rule details' option from the Alert Details' Actions list when the rule is deleted ({kibana-pull}163183[#163183]). +Reporting:: +* Fixes a bug where Kibana Reporting would not work in Elastic Docker without adding a special setting in kibana.yml to disable the Chromium sandbox. ({kibana-pull}149080[#149080]). +* Fixes an issue where certain international characters would not appear correctly in the contents of a print-optimized PDF report of a dashboard ({kibana-pull}161825[#161825]). +Uptime:: +* Fixes auto-expand feature for failed step detail ({kibana-pull}162747[#162747]). + [[release-notes-8.9.1]] == {kib} 8.9.1 diff --git a/docs/api-generated/rules/rule-apis-passthru.asciidoc b/docs/api-generated/rules/rule-apis-passthru.asciidoc index 63aad889c865c..843f073f95e04 100644 --- a/docs/api-generated/rules/rule-apis-passthru.asciidoc +++ b/docs/api-generated/rules/rule-apis-passthru.asciidoc @@ -45,6 +45,7 @@ Any modifications made to this file will be overwritten.
  • post /s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_unmute
  • post /s/{spaceId}/api/alerting/rule/{ruleId}/_unmute_all
  • put /s/{spaceId}/api/alerting/rule/{ruleId}
  • +
  • post /s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key
  • Alerting

    @@ -2827,12 +2828,61 @@ Any modifications made to this file will be overwritten. 404_response
    +
    +
    + Up +
    post /s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key
    +
    Updates the API key for a rule. (updateRuleAPIKey)
    +
    The new API key has the credentials of the user that submits the request.
    + +

    Path parameters

    +
    +
    ruleId (required)
    + +
    Path Parameter — An identifier for the rule. default: null
    spaceId (required)
    + +
    Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
    +
    + + + +

    Request headers

    +
    +
    kbn-xsrf (required)
    + +
    Header Parameter — Cross-site request forgery protection default: null
    + +
    + + + + + + + +

    Produces

    + This API call produces the following media types according to the Accept request header; + the media type will be conveyed by the Content-Type response header. +
      +
    • application/json
    • +
    + +

    Responses

    +

    200

    + Indicates a successful call. + +

    400

    + Bad request + 400_response +
    +

    Models

    [ Jump to Methods ]

    Table of Contents

      +
    1. 400_response - Bad request
    2. 401_response - Unsuccessful rule API response
    3. 404_response -
    4. Count - Count
    5. @@ -2969,6 +3019,19 @@ Any modifications made to this file will be overwritten.
    6. update_rule_request - Update rule request
    +
    +

    400_response - Bad request Up

    +
    +
    +
    error
    +
    Enum:
    +
    Bad Request
    +
    message
    +
    statusCode
    +
    Enum:
    +
    400
    +
    +

    401_response - Unsuccessful rule API response Up

    diff --git a/docs/api/role-management/put.asciidoc b/docs/api/role-management/put.asciidoc index b6338f79812a7..5061276078295 100644 --- a/docs/api/role-management/put.asciidoc +++ b/docs/api/role-management/put.asciidoc @@ -26,7 +26,7 @@ To use the create or update role API, you must have the `manage_security` cluste `elasticsearch`:: (Optional, object) {es} cluster and index privileges. Valid keys include - `cluster`, `indices`, and `run_as`. For more information, see + `cluster`, `indices`, `remote_indices`, and `run_as`. For more information, see {ref}/defining-roles.html[Defining roles]. `kibana`:: @@ -63,7 +63,7 @@ To use the create or update role API, you must have the `manage_security` cluste `204`:: Indicates a successful call. -'409':: +`409`:: When `createOnly` is true, indicates a conflict with an existing role. ==== Examples @@ -74,60 +74,32 @@ Grant access to various features in all spaces: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { - "metadata" : { - "version" : 1 + "metadata": { + "version": 1 }, "elasticsearch": { - "cluster" : [ ], - "indices" : [ ] + "cluster": [ ], + "indices": [ ] }, "kibana": [ { - "base": [], + "base": [ ], "feature": { - "discover": [ - "all" - ], - "visualize": [ - "all" - ], - "dashboard": [ - "all" - ], - "dev_tools": [ - "read" - ], - "advancedSettings": [ - "read" - ], - "indexPatterns": [ - "read" - ], - "graph": [ - "all" - ], - "apm": [ - "read" - ], - "maps": [ - "read" - ], - "canvas": [ - "read" - ], - "infrastructure": [ - "all" - ], - "logs": [ - "all" - ], - "uptime": [ - "all" - ] + "discover": [ "all" ], + "visualize": [ "all" ], + "dashboard": [ "all" ], + "dev_tools": [ "read" ], + "advancedSettings": [ "read" ], + "indexPatterns": [ "read" ], + "graph": [ "all" ], + "apm": [ "read" ], + "maps": [ "read" ], + "canvas": [ "read" ], + "infrastructure": [ "all" ], + "logs": [ "all" ], + "uptime": [ "all" ] }, - "spaces": [ - "*" - ] + "spaces": [ "*" ] } ] } @@ -140,22 +112,20 @@ Grant dashboard-only access to only the Marketing space: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { - "metadata" : { - "version" : 1 + "metadata": { + "version": 1 }, "elasticsearch": { - "cluster" : [ ], - "indices" : [ ] + "cluster": [ ], + "indices": [ ] }, "kibana": [ { - "base": [], + "base": [ ], "feature": { - "dashboard": ["read"] + "dashboard": [ "read" ] }, - "spaces": [ - "marketing" - ] + "spaces": [ "marketing" ] } ] } @@ -168,21 +138,18 @@ Grant full access to all features in the Default space: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { - "metadata" : { - "version" : 1 + "metadata": { + "version": 1 }, "elasticsearch": { - "cluster" : [ ], - "indices" : [ ] + "cluster": [ ], + "indices": [ ] }, "kibana": [ { - "base": ["all"], - "feature": { - }, - "spaces": [ - "default" - ] + "base": [ "all" ], + "feature": { }, + "spaces": [ "default" ] } ] } @@ -195,30 +162,25 @@ Grant different access to different spaces: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { - "metadata" : { - "version" : 1 + "metadata": { + "version": 1 }, "elasticsearch": { - "cluster" : [ ], - "indices" : [ ] + "cluster": [ ], + "indices": [ ] }, "kibana": [ { - "base": [], + "base": [ ], "feature": { - "discover": ["all"], - "dashboard": ["all"] + "discover": [ "all" ], + "dashboard": [ "all" ] }, - "spaces": [ - "default" - ] + "spaces": [ "default" ] }, { - "base": ["read"], - "spaces": [ - "marketing", - "sales" - ] + "base": [ "read"] , + "spaces": [ "marketing", "sales" ] } ] } @@ -231,28 +193,30 @@ Grant access to {kib} and {es}: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { - "metadata" : { - "version" : 1 + "metadata": { + "version": 1 }, "elasticsearch": { - "cluster" : [ "all" ], - "indices" : [ { - "names" : [ "index1", "index2" ], - "privileges" : [ "all" ], - "field_security" : { - "grant" : [ "title", "body" ] - }, - "query" : "{\"match\": {\"title\": \"foo\"}}" - } ] + "cluster": [ "all" ], + "indices": [ + { + "names": [ "index1", "index2" ], + "privileges": [ "all" ] + } + ], + "remote_indices": [ + { + "clusters": [ "remote_cluster1" ], + "names": [ "remote_index1", "remote_index2" ], + "privileges": [ "all" ] + } + ] }, "kibana": [ { - "base": ["all"], - "feature": { - }, - "spaces": [ - "default" - ] + "base": [ "all" ], + "feature": { }, + "spaces": [ "default" ] } ] } diff --git a/docs/api/saved-objects/bulk_create.asciidoc b/docs/api/saved-objects/bulk_create.asciidoc index 9639a70d4387b..bde9b7861183f 100644 --- a/docs/api/saved-objects/bulk_create.asciidoc +++ b/docs/api/saved-objects/bulk_create.asciidoc @@ -8,6 +8,12 @@ deprecated::[8.7.0, To be removed in an upcoming version] Create multiple {kib} saved objects. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-bulk-create-request]] ==== Request diff --git a/docs/api/saved-objects/bulk_delete.asciidoc b/docs/api/saved-objects/bulk_delete.asciidoc index 9a06cb7ea9f9d..dc1c218467a65 100644 --- a/docs/api/saved-objects/bulk_delete.asciidoc +++ b/docs/api/saved-objects/bulk_delete.asciidoc @@ -10,6 +10,12 @@ Remove multiple {kib} saved objects. WARNING: Once you delete a saved object, _it cannot be recovered_. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + ==== Request `POST :/api/saved_objects/_bulk_delete` diff --git a/docs/api/saved-objects/bulk_get.asciidoc b/docs/api/saved-objects/bulk_get.asciidoc index 78e1a1e60ca25..9807d7b499400 100644 --- a/docs/api/saved-objects/bulk_get.asciidoc +++ b/docs/api/saved-objects/bulk_get.asciidoc @@ -8,6 +8,12 @@ deprecated::[8.7.0, To be removed in an upcoming version] Retrieve multiple {kib} saved objects by ID. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-bulk-get-request]] ==== Request diff --git a/docs/api/saved-objects/bulk_resolve.asciidoc b/docs/api/saved-objects/bulk_resolve.asciidoc index 637e268f49cbf..6908b0f7b7dd0 100644 --- a/docs/api/saved-objects/bulk_resolve.asciidoc +++ b/docs/api/saved-objects/bulk_resolve.asciidoc @@ -12,6 +12,12 @@ Under certain circumstances, when Kibana is upgraded, saved object migrations ma features. When an object's ID is regenerated, a legacy URL alias is created for that object, preserving its old ID. In such a scenario, that object can be retrieved via the Bulk Resolve API using either its new ID or its old ID. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-bulk-resolve-request]] ==== Request diff --git a/docs/api/saved-objects/bulk_update.asciidoc b/docs/api/saved-objects/bulk_update.asciidoc index 529f9bbb406aa..dfc16f87c9d4c 100644 --- a/docs/api/saved-objects/bulk_update.asciidoc +++ b/docs/api/saved-objects/bulk_update.asciidoc @@ -8,6 +8,12 @@ deprecated::[8.7.0, To be removed in an upcoming version] Update the attributes for multiple existing {kib} saved objects. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-bulk-update-request]] ==== Request diff --git a/docs/api/saved-objects/create.asciidoc b/docs/api/saved-objects/create.asciidoc index e955cbf61693c..7e26a329fb54d 100644 --- a/docs/api/saved-objects/create.asciidoc +++ b/docs/api/saved-objects/create.asciidoc @@ -8,6 +8,12 @@ deprecated::[8.7.0, To be removed in an upcoming version] Create {kib} saved objects. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-create-request]] ==== Request diff --git a/docs/api/saved-objects/delete.asciidoc b/docs/api/saved-objects/delete.asciidoc index d0830a8002eb6..565d684757495 100644 --- a/docs/api/saved-objects/delete.asciidoc +++ b/docs/api/saved-objects/delete.asciidoc @@ -10,6 +10,12 @@ Remove {kib} saved objects. WARNING: Once you delete a saved object, _it cannot be recovered_. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-delete-request]] ==== Request diff --git a/docs/api/saved-objects/find.asciidoc b/docs/api/saved-objects/find.asciidoc index 12955c807c299..8efc20cb11a90 100644 --- a/docs/api/saved-objects/find.asciidoc +++ b/docs/api/saved-objects/find.asciidoc @@ -8,6 +8,12 @@ deprecated::[8.7.0, To be removed in an upcoming version] Retrieve a paginated set of {kib} saved objects by various conditions. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-find-request]] ==== Request diff --git a/docs/api/saved-objects/get.asciidoc b/docs/api/saved-objects/get.asciidoc index 7f375994d98de..2e7a5f949832b 100644 --- a/docs/api/saved-objects/get.asciidoc +++ b/docs/api/saved-objects/get.asciidoc @@ -8,6 +8,12 @@ deprecated::[8.7.0, To be removed in an upcoming version] Retrieve a single {kib} saved object by ID. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-get-request]] ==== Request diff --git a/docs/api/saved-objects/resolve.asciidoc b/docs/api/saved-objects/resolve.asciidoc index 9fec2b1724f77..7d9176145fbcc 100644 --- a/docs/api/saved-objects/resolve.asciidoc +++ b/docs/api/saved-objects/resolve.asciidoc @@ -12,6 +12,12 @@ Under certain circumstances, when Kibana is upgraded, saved object migrations ma features. When an object's ID is regenerated, a legacy URL alias is created for that object, preserving its old ID. In such a scenario, that object can be retrieved via the Resolve API using either its new ID or its old ID. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-resolve-request]] ==== Request diff --git a/docs/api/saved-objects/resolve_import_errors.asciidoc b/docs/api/saved-objects/resolve_import_errors.asciidoc index ca156900390dc..7092ce20e01d3 100644 --- a/docs/api/saved-objects/resolve_import_errors.asciidoc +++ b/docs/api/saved-objects/resolve_import_errors.asciidoc @@ -14,6 +14,12 @@ To resolve errors, you can: * Change references to different saved objects +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-resolve-import-errors-request]] ==== Request diff --git a/docs/api/saved-objects/rotate_encryption_key.asciidoc b/docs/api/saved-objects/rotate_encryption_key.asciidoc index efc57ddb4308d..8b45ee7175599 100644 --- a/docs/api/saved-objects/rotate_encryption_key.asciidoc +++ b/docs/api/saved-objects/rotate_encryption_key.asciidoc @@ -7,6 +7,12 @@ experimental[] Rotate the encryption key for encrypted saved objects. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + If a saved object cannot be decrypted using the primary encryption key, then {kib} will attempt to decrypt it using the specified <>. In most of the cases this overhead is negligible, but if you're dealing with a large number of saved objects and experiencing performance issues, you may want to rotate the encryption key. [IMPORTANT] diff --git a/docs/api/saved-objects/update.asciidoc b/docs/api/saved-objects/update.asciidoc index bc99e264db122..28e8956edb528 100644 --- a/docs/api/saved-objects/update.asciidoc +++ b/docs/api/saved-objects/update.asciidoc @@ -8,6 +8,12 @@ deprecated::[8.7.0, To be removed in an upcoming version] Update the attributes for existing {kib} saved objects. +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/packages/core/saved-objects/docs/openapi[open API specification]. +==== + [[saved-objects-api-update-request]] ==== Request diff --git a/docs/concepts/data-views.asciidoc b/docs/concepts/data-views.asciidoc index f75012e8d69f4..c72679734b725 100644 --- a/docs/concepts/data-views.asciidoc +++ b/docs/concepts/data-views.asciidoc @@ -143,15 +143,20 @@ all clusters having a name starting with `cluster_`: `cluster_*:logstash-*,cluster_*:-logstash-old*` ``` -To exclude a cluster having a name starting with `cluster_`: +Excluding a cluster avoids sending any network calls to that cluster. +To exclude a cluster with the name `cluster_one`: ```ts -`cluster_*:logstash-*,cluster_one:-*` +`cluster_*:logstash-*,-cluster_one:*` ``` Once you configure a {data-source} to use the {ccs} syntax, all searches and aggregations using that {data-source} in {kib} take advantage of {ccs}. +For more information, refer to +{ref}/modules-cross-cluster-search.html#exclude-problematic-clusters[Excluding +clusters or indicies from cross-cluster search]. + [float] [[delete-data-view]] === Delete a {data-source} diff --git a/docs/developer/advanced/sharing-saved-objects.asciidoc b/docs/developer/advanced/sharing-saved-objects.asciidoc index b221dbc275dd0..27fe81702cd2a 100644 --- a/docs/developer/advanced/sharing-saved-objects.asciidoc +++ b/docs/developer/advanced/sharing-saved-objects.asciidoc @@ -166,7 +166,7 @@ const savedObject = resolveResult.saved_object; TIP: See an example of this in https://github.com/elastic/kibana/pull/107256#user-content-example-steps[step 2 of the POC]! The -https://github.com/elastic/kibana/blob/main/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveresponse.md[SavedObjectsResolveResponse +{kib-repo}blob/{branch}/packages/core/saved-objects/core-saved-objects-api-server/src/apis/resolve.ts[SavedObjectsResolveResponse interface] has four fields, summarized below: * `saved_object` - The saved object that was found. @@ -373,7 +373,7 @@ image::images/sharing-saved-objects-step-6.png["Sharing Saved Objects registrati > *Update saved object delete API usage to handle multiple spaces* If an object is shared to multiple spaces, it cannot be deleted without using the -https://github.com/elastic/kibana/blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeleteoptions.md[`force` +{kib-repo}blob/{branch}/packages/core/saved-objects/core-saved-objects-api-server/src/apis/delete.ts[`force` delete option]. You should always be aware when a saved object exists in multiple spaces, and you should warn users in that case. If your UI allows users to delete your objects, you can define a warning message like this: @@ -477,7 +477,7 @@ return ( 2. Allow users to access your objects in the <> in <>. You can do this by ensuring that your objects are marked as - https://github.com/elastic/kibana/blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md[importable and exportable] in your <>: + {kib-repo}blob/{branch}/packages/core/saved-objects/core-saved-objects-server/src/saved_objects_management.ts[importable and exportable] in your <>: + ```ts name: 'my-object-type', diff --git a/docs/developer/architecture/add-data-tutorials.asciidoc b/docs/developer/architecture/add-data-tutorials.asciidoc index 3f1b42c008ee7..7a756dd61b18f 100644 --- a/docs/developer/architecture/add-data-tutorials.asciidoc +++ b/docs/developer/architecture/add-data-tutorials.asciidoc @@ -16,7 +16,7 @@ Each tutorial contains three sets of instructions: The function must return a function object that conforms to the `TutorialSchema` interface link:{kib-repo}tree/{branch}/src/plugins/home/server/services/tutorials/lib/tutorial_schema.ts[tutorial schema]. 3. Register the tutorial in link:{kib-repo}tree/{branch}/src/plugins/home/server/tutorials/register.ts[register.ts] by adding it to the `builtInTutorials`. // TODO update path once assets are migrated -4. Add image assets to the link:{kib-repo}tree/{branch}/src/legacy/core_plugins/kibana/public/home/tutorial_resources[tutorial_resources directory]. +4. Add image assets to the `tutorial_resources` directory. 5. Run {kib} locally to preview the tutorial. 6. Create a PR and go through the review process to get the changes approved. @@ -34,5 +34,5 @@ link:{kib-repo}tree/{branch}/src/plugins/home/public/application/components/tuto ==== Markdown String values can contain limited Markdown syntax. -link:{kib-repo}tree/{branch}/src/legacy/core_plugins/kibana/public/home/components/tutorial/content.js[Enabled Markdown grammars] +https://elastic.github.io/eui/#/editors-syntax/markdown-format[Enabled Markdown grammars] diff --git a/docs/developer/architecture/development/csv-integration.asciidoc b/docs/developer/architecture/development/csv-integration.asciidoc index 8ccd33f5f24ed..45b4e50e06240 100644 --- a/docs/developer/architecture/development/csv-integration.asciidoc +++ b/docs/developer/architecture/development/csv-integration.asciidoc @@ -21,7 +21,7 @@ interface jobParameters { } ---- -The `searchRequest.body` should abide by the {ref}/search-request-body.html[Elasticsearch Search Request Body] syntax +The `searchRequest.body` should abide by the {ref}/search-search.html[Elasticsearch Search Request Body] syntax [float] ==== `export-config` Directive @@ -48,4 +48,4 @@ function getSharingTitle() string; ---- -The `sharingData.searchRequest.body` should abide by the {ref}/search-request-body.html[Elasticsearch Search Request Body] syntax \ No newline at end of file +The `sharingData.searchRequest.body` should abide by the {ref}/search-search.html[{es} Search Request Body] syntax \ No newline at end of file diff --git a/docs/developer/architecture/index.asciidoc b/docs/developer/architecture/index.asciidoc index 36be54a384b17..fa68f13939eb9 100644 --- a/docs/developer/architecture/index.asciidoc +++ b/docs/developer/architecture/index.asciidoc @@ -14,7 +14,7 @@ To begin plugin development, we recommend reading our overview of how plugins wo Our developer services are changing all the time. One of the best ways to discover and learn about them is to read the available READMEs inside our plugins folders: {kib-repo}tree/{branch}/src/plugins[src/plugins] and -{kib-repo}/tree/{branch}/x-pack/plugins[x-pack/plugins]. +{kib-repo}tree/{branch}/x-pack/plugins[x-pack/plugins]. A few services also automatically generate api documentation which can be browsed inside the {kib-repo}tree/{branch}/docs/development[docs/development section of our repo] diff --git a/docs/developer/architecture/kibana-platform-plugin-api.asciidoc b/docs/developer/architecture/kibana-platform-plugin-api.asciidoc index 58ad9665f8495..85fc05d0f9fd8 100644 --- a/docs/developer/architecture/kibana-platform-plugin-api.asciidoc +++ b/docs/developer/architecture/kibana-platform-plugin-api.asciidoc @@ -44,14 +44,14 @@ plugin and to specify if this plugin has server-side code, browser-side code, or } ---- -Learn about the {kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md[manifest +Learn about the {kib-repo}blob/{branch}/packages/core/plugins/core-plugins-server/src/types.ts[manifest file format]. NOTE: `package.json` files are irrelevant to and ignored by {kib} for discovering and loading plugins. *[2] `public/index.ts`* is the entry point into the client-side code of this plugin. It must export a function named `plugin`, which will -receive {kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.plugininitializercontext.md[a standard set of core capabilities] as an argument. +receive {kib-repo}blob/{branch}/packages/core/plugins/core-plugins-browser/src/plugin_initializer.ts[a standard set of core capabilities] as an argument. It should return an instance of its plugin class for {kib} to load. @@ -93,7 +93,7 @@ export class MyPlugin implements Plugin { ---- *[4] `server/index.ts`* is the entry-point into the server-side code of -this plugin. {kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.plugininitializercontext.md[It is identical] in almost every way to the client-side +this plugin. {kib-repo}blob/{branch}/packages/core/plugins/core-plugins-server/src/types.ts[It is identical] in almost every way to the client-side entry-point: @@ -221,16 +221,16 @@ These are the contracts exposed by the core services for each lifecycle: |=== |lifecycle |server contract|browser contract |_constructor_ -|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.plugininitializercontext.md[PluginInitializerContext] -|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.plugininitializercontext.md[PluginInitializerContext] +|{kib-repo}blob/{branch}/packages/core/plugins/core-plugins-server/src/types.ts[PluginInitializerContext] +|{kib-repo}blob/{branch}/packages/core/plugins/core-plugins-browser/src/plugin_initializer.ts[PluginInitializerContext] |_setup_ -|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.coresetup.md[CoreSetup] -|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.coresetup.md[CoreSetup] +|{kib-repo}blob/{branch}/packages/core/lifecycle/core-lifecycle-server/src/core_setup.ts[CoreSetup] +|{kib-repo}blob/{branch}/packages/core/lifecycle/core-lifecycle-browser-internal/src/internal_core_setup.ts[CoreSetup] |_start_ -|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.corestart.md[CoreStart] -|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.corestart.md[CoreStart] +|{kib-repo}blob/{branch}/packages/core/lifecycle/core-lifecycle-server/src/core_start.ts[CoreStart] +|{kib-repo}blob/{branch}/packages/core/lifecycle/core-lifecycle-browser/src/core_start.ts[CoreStart] |_stop_ | |=== @@ -283,7 +283,7 @@ export class MyPlugin implements Plugin { Unlike core, capabilities exposed by plugins are _not_ automatically injected into all plugins. Instead, if a plugin wishes to use the public interface provided by another plugin, it must first declare that -plugin as a dependency in it's {kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md[`kibana.json`] manifest file. +plugin as a dependency in it's {kib-repo}blob/{branch}/packages/core/plugins/core-plugins-server/src/types.ts[`kibana.json`] manifest file. *demo kibana.json:* diff --git a/docs/developer/architecture/security/feature-registration.asciidoc b/docs/developer/architecture/security/feature-registration.asciidoc index 4e0c220477faf..c9d173a6be6fb 100644 --- a/docs/developer/architecture/security/feature-registration.asciidoc +++ b/docs/developer/architecture/security/feature-registration.asciidoc @@ -39,7 +39,7 @@ Registering a feature consists of the following fields. For more information, co |A human readable name for your feature. |`category` (required) -|{kib-repo}blob/{branch}/src/core/types/app_category.ts[`AppCategory`] +|{kib-repo}blob/{branch}/packages/core/application/core-application-common/src/app_category.ts[`AppCategory`] |`DEFAULT_APP_CATEGORIES.kibana` |The `AppCategory` which best represents your feature. Used to organize the display of features within the management screens. @@ -50,12 +50,12 @@ of features within the management screens. |An array of applications this feature enables. Typically, all of your plugin's apps (from `uiExports`) will be included here. |`privileges` (required) -|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`KibanaFeatureConfig`]. +|{kib-repo}blob/{branch}/x-pack/plugins/features/common/kibana_feature.ts[`KibanaFeatureConfig`]. |See <> and <> |The set of privileges this feature requires to function. |`subFeatures` (optional) -|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`KibanaFeatureConfig`]. +|{kib-repo}blob/{branch}/x-pack/plugins/features/common/kibana_feature.ts[`KibanaFeatureConfig`]. |See <> |The set of subfeatures that enables finer access control than the `all` and `read` feature privileges. These options are only available in the Gold subscription level and higher. diff --git a/docs/developer/best-practices/index.asciidoc b/docs/developer/best-practices/index.asciidoc index afdd500fddc3f..57a10ee06a697 100644 --- a/docs/developer/best-practices/index.asciidoc +++ b/docs/developer/best-practices/index.asciidoc @@ -78,7 +78,7 @@ strategies] *** Use the `esSearchStrategy` to make raw queries to ES that will support async searching and partial results, as well as injecting the right advanced settings like whether to include frozen indices or not. -* {kib-repo}tree/{branch}/src/plugins/embeddable/README.asciidoc[Embeddables] +* {kib-repo}blob/{branch}/src/plugins/embeddable/README.md[Embeddables] ** Rendering maps, visualizations, dashboards in your application ** Register new widgets that will can be added to a dashboard or Canvas workpad, or rendered in another plugin. @@ -105,8 +105,8 @@ Eventually we want to guarantee to our plugin developers that their plugins will Any time you create or change a public API, keep this in mind, and consider potential backward compatibility issues. While we have a formal -{kib-repo}tree/{branch}/src/core/server/saved_objects/migrations/README.md[saved -object migration system] and are working on adding a formal state migration system, introducing state changes and migrations in a +saved +object migration system and are working on adding a formal state migration system, introducing state changes and migrations in a minor always comes with a risk. Consider this before making huge and risky changes in minors, _especially_ to saved objects. diff --git a/docs/developer/best-practices/navigation.asciidoc b/docs/developer/best-practices/navigation.asciidoc index e969f00c41eb1..20c52b40978c4 100644 --- a/docs/developer/best-practices/navigation.asciidoc +++ b/docs/developer/best-practices/navigation.asciidoc @@ -25,7 +25,7 @@ Assuming you want to link from your app to *Discover*. When building such URL th ==== Prepending a proper `basePath` -To prepend {kib}'s `basePath` use {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.ibasepath.prepend.md[core.http.basePath.prepend] helper: +To prepend {kib}'s `basePath` use {kib-repo}tree/{branch}/packages/core/http/core-http-browser-internal/src/base_path.ts[core.http.basePath.prepend] helper: [source,typescript jsx] ---- @@ -58,7 +58,7 @@ const discoverUrl = await plugins.discover.locator.getUrl({filters, timeRange}); await plugins.discover.locator.navigate({filters, timeRange}); ---- -To get a better idea, take a look at *Discover* locator {kib-repo}tree/{branch}/src/plugins/discover/public/locator.ts[implementation]. +To get a better idea, take a look at *Discover* locator {kib-repo}tree/{branch}/src/plugins/discover/public/application/doc/locator.ts[implementation]. It allows specifying various **Discover** app state pieces like: index pattern, filters, query, time range and more. There are two ways to access locators of other apps: @@ -87,12 +87,13 @@ window.location.href = urlToADashboard; To navigate between different {kib} apps without a page reload (by default) there are APIs in `core`: -* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetoapp.md[core.application.navigateToApp] -* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md[core.application.navigateToUrl] +* {kib-repo}tree/{branch}/packages/core/application/core-application-browser/src/contracts.ts[core.application.navigateToApp] +* {kib-repo}tree/{branch}/packages/core/application/core-application-browser/src/contracts.ts[core.application.navigateToUrl] Both methods offer customization such as opening the target in a new page, with an `options` parameter. All the options are optional be default. -* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.navigatetoappoptions.md[core.application.navigateToApp options] -* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.md[core.application.navigateToUrl options] + +* {kib-repo}tree/{branch}/packages/core/application/core-application-browser/src/contracts.ts[core.application.navigateToApp options] +* {kib-repo}tree/{branch}/packages/core/application/core-application-browser/src/contracts.ts[core.application.navigateToUrl options] *Rendering a link to a different {kib} app on its own would also cause a full page reload:* @@ -162,8 +163,8 @@ Common rules to follow in this scenario: This is required to make sure `core` is aware of navigations triggered inside your app, so it could act accordingly when needed. -* `Core`'s {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] instance. -* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.appmountparameters.history.md[Example usage] +* `Core`'s {kib-repo}tree/{branch}/packages/core/application/core-application-browser/src/scoped_history.ts[ScopedHistory] instance. +* {kib-repo}tree/{branch}/packages/core/application/core-application-browser/src/app_mount.ts[Example usage] * {kib-repo}tree/{branch}/test/plugin_functional/plugins/core_plugin_a/public/application.tsx#L120[Example plugin] Relative links will be resolved relative to your app's route (e.g.: `http://localhost5601/app/{your-app-id}`) @@ -180,14 +181,14 @@ const MyInternalLink = () => === Using history and browser location Try to avoid using `window.location` and `window.history` directly. + -Instead, consider using {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] +Instead, consider using {kib-repo}tree/{branch}/packages/core/application/core-application-browser/src/scoped_history.ts[ScopedHistory] instance provided by `core`. * This way `core` will know about location changes triggered within your app, and it would act accordingly. * Some plugins are listening to location changes. Triggering location change manually could lead to unpredictable and hard-to-catch bugs. Common use-case for using -`core`'s {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] directly: +`core`'s {kib-repo}tree/{branch}/packages/core/application/core-application-browser/src/scoped_history.ts[ScopedHistory] directly: * Reading/writing query params or hash. * Imperatively triggering internal navigations within your app. diff --git a/docs/developer/contributing/development-functional-tests.asciidoc b/docs/developer/contributing/development-functional-tests.asciidoc index 55bc6f6b8c398..d149372f0f572 100644 --- a/docs/developer/contributing/development-functional-tests.asciidoc +++ b/docs/developer/contributing/development-functional-tests.asciidoc @@ -118,7 +118,7 @@ The tests are written in https://mochajs.org[mocha] using https://github.com/ela We use https://www.w3.org/TR/webdriver1/[WebDriver Protocol] to run tests in both Chrome and Firefox with the help of https://sites.google.com/a/chromium.org/chromedriver/[chromedriver] and https://firefox-source-docs.mozilla.org/testing/geckodriver/[geckodriver]. When the `FunctionalTestRunner` launches, remote service creates a new webdriver session, which starts the driver and a stripped-down browser instance. We use `browser` service and `webElementWrapper` class to wrap up https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/[Webdriver API]. -The `FunctionalTestRunner` automatically transpiles functional tests using babel, so that tests can use the same ECMAScript features that {kib} source code uses. See {kibana-blob}style_guides/js_style_guide.md[style_guides/js_style_guide.md]. +The `FunctionalTestRunner` automatically transpiles functional tests using babel, so that tests can use the same ECMAScript features that {kib} source code uses. See {kibana-blob}/STYLEGUIDE.mdx[STYLEGUIDE.mdx]. [discrete] ==== Definitions @@ -270,7 +270,7 @@ The first and only argument to all providers is a Provider API Object. This obje Within config files the API has the following properties [horizontal] -`log`::: An instance of the {kibana-blob}packages/kbn-dev-utils/src/tooling_log/tooling_log.js[`ToolingLog`] that is ready for use +`log`::: An instance of the `ToolingLog` that is ready for use `readConfigFile(path)`::: Returns a promise that will resolve to a Config instance that provides the values from the config file at `path` Within service and PageObject Providers the API is: @@ -293,17 +293,17 @@ Within a test Provider the API is exactly the same as the service providers API The `FunctionalTestRunner` comes with three built-in services: **config:**::: -* Source: {kibana-blob}src/functional_test_runner/lib/config/config.ts[src/functional_test_runner/lib/config/config.ts] -* Schema: {kibana-blob}src/functional_test_runner/lib/config/schema.ts[src/functional_test_runner/lib/config/schema.ts] +// * Source: {kibana-blob}src/functional_test_runner/lib/config/config.ts[src/functional_test_runner/lib/config/config.ts] +// * Schema: {kibana-blob}src/functional_test_runner/lib/config/schema.ts[src/functional_test_runner/lib/config/schema.ts] * Use `config.get(path)` to read any value from the config file **log:**::: -* Source: {kibana-blob}packages/kbn-dev-utils/src/tooling_log/tooling_log.js[packages/kbn-dev-utils/src/tooling_log/tooling_log.js] +// * Source: {kibana-blob}packages/kbn-dev-utils/src/tooling_log/tooling_log.js[packages/kbn-dev-utils/src/tooling_log/tooling_log.js] * `ToolingLog` instances are readable streams. The instance provided by this service is automatically piped to stdout by the `FunctionalTestRunner` CLI * `log.verbose()`, `log.debug()`, `log.info()`, `log.warning()` all work just like console.log but produce more organized output **lifecycle:**::: -* Source: {kibana-blob}src/functional_test_runner/lib/lifecycle.ts[src/functional_test_runner/lib/lifecycle.ts] +// * Source: {kibana-blob}src/functional_test_runner/lib/lifecycle.ts[src/functional_test_runner/lib/lifecycle.ts] * Designed primary for use in services * Exposes lifecycle events for basic coordination. Handlers can return a promise and resolve/fail asynchronously * Phases include: `beforeLoadTests`, `beforeTests`, `beforeEachTest`, `cleanup` @@ -314,14 +314,14 @@ The `FunctionalTestRunner` comes with three built-in services: The {kib} functional tests define the vast majority of the actual functionality used by tests. **browser**::: -* Source: {kibana-blob}test/functional/services/browser.ts[test/functional/services/browser.ts] +// * Source: {kibana-blob}test/functional/services/browser.ts[test/functional/services/browser.ts] * Higher level wrapper for `remote` service, which exposes available browser actions * Popular methods: ** `browser.getWindowSize()` ** `browser.refresh()` **testSubjects:**::: -* Source: {kibana-blob}test/functional/services/test_subjects.ts[test/functional/services/test_subjects.ts] +// * Source: {kibana-blob}test/functional/services/test_subjects.ts[test/functional/services/test_subjects.ts] * Test subjects are elements that are tagged specifically for selecting from tests * Use `testSubjects` over CSS selectors when possible * Usage: @@ -346,21 +346,21 @@ await testSubjects.click(‘containerButton’); ** `testSubjects.click(testSubjectSelector)` - Click a test subject in the page; throw if it can't be found after some time **find:**::: -* Source: {kibana-blob}test/functional/services/find.ts[test/functional/services/find.ts] +// * Source: {kibana-blob}test/functional/services/find.ts[test/functional/services/find.ts] * Helpers for `remote.findBy*` methods that log and manage timeouts * Popular methods: ** `find.byCssSelector()` ** `find.allByCssSelector()` **retry:**::: -* Source: {kibana-blob}test/common/services/retry/retry.ts[test/common/services/retry/retry.ts] +// * Source: {kibana-blob}test/common/services/retry/retry.ts[test/common/services/retry/retry.ts] * Helpers for retrying operations * Popular methods: ** `retry.try(fn, onFailureBlock)` - Execute `fn` in a loop until it succeeds or the default timeout elapses. The optional `onFailureBlock` is executed before each retry attempt. ** `retry.tryForTime(ms, fn, onFailureBlock)` - Execute `fn` in a loop until it succeeds or `ms` milliseconds elapses. The optional `onFailureBlock` is executed before each retry attempt. **kibanaServer:**::: -* Source: {kibana-blob}test/common/services/kibana_server/kibana_server.js[test/common/services/kibana_server/kibana_server.js] +// * Source: {kibana-blob}test/common/services/kibana_server/kibana_server.js[test/common/services/kibana_server/kibana_server.js] * Helpers for interacting with {kib}'s server * Commonly used methods: ** `kibanaServer.uiSettings.update()` @@ -368,7 +368,7 @@ await testSubjects.click(‘containerButton’); ** `kibanaServer.status.getOverallState()` **esArchiver:**::: -* Source: {kibana-blob}test/common/services/es_archiver.ts[test/common/services/es_archiver.ts] +// * Source: {kibana-blob}test/common/services/es_archiver.ts[test/common/services/es_archiver.ts] * Load/unload archives created with the `esArchiver` * Popular methods: ** `esArchiver.load(path)` @@ -380,11 +380,11 @@ Full list of services that are used in functional tests can be found here: {kiba **Low-level utilities:**::: * es -** Source: {kibana-blob}test/common/services/es.ts[test/common/services/es.ts] +// ** Source: {kibana-blob}test/common/services/es.ts[test/common/services/es.ts] ** {es} client ** Higher level options: `kibanaServer.uiSettings` or `esArchiver` * remote -** Source: {kibana-blob}test/functional/services/remote/remote.ts[test/functional/services/remote/remote.ts] +// ** Source: {kibana-blob}test/functional/services/remote/remote.ts[test/functional/services/remote/remote.ts] ** Instance of https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html[WebDriver] class ** Responsible for all communication with the browser ** To perform browser actions, use `remote` service diff --git a/docs/developer/contributing/linting.asciidoc b/docs/developer/contributing/linting.asciidoc index 1cd56ab65b669..6470206aea0eb 100644 --- a/docs/developer/contributing/linting.asciidoc +++ b/docs/developer/contributing/linting.asciidoc @@ -2,7 +2,7 @@ == Linting A note about linting: We use http://eslint.org[eslint] to check that the -link:STYLEGUIDE.mdx[styleguide] is being followed. It runs in a +{kib-repo}blob/{branch}/STYLEGUIDE.mdx[styleguide] is being followed. It runs in a pre-commit hook and as a part of the tests, but most contributors integrate it with their code editors for real-time feedback. diff --git a/docs/developer/getting-started/index.asciidoc b/docs/developer/getting-started/index.asciidoc index 795cb45c3dfd9..aa78976058172 100644 --- a/docs/developer/getting-started/index.asciidoc +++ b/docs/developer/getting-started/index.asciidoc @@ -72,10 +72,7 @@ you can use: yarn kbn bootstrap --force-install ---- -(You can also run `yarn kbn` to see the other available commands. For -more info about this tool, see -{kib-repo}tree/{branch}/packages/kbn-pm[{kib-repo}tree/{branch}/packages/kbn-pm]. If you want more -information about how to actively develop over packages please read <>) +You can also run `yarn kbn` to see the other available commands. When switching branches which use different versions of npm packages you may need to run: diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index e8c008af6e0e8..9321e7499f9b4 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -254,6 +254,10 @@ It also provides a stateful version of it on the start contract. Content is fetched from the remote (https://feeds.elastic.co) once a day, with periodic checks if the content needs to be refreshed. All newsfeed content is hosted remotely. +|{kib-repo}blob/{branch}/src/plugins/no_data_page/README.md[noDataPage] +|Helps to globally configure the no data page components + + |{kib-repo}blob/{branch}/src/plugins/presentation_util/README.mdx[presentationUtil] |The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). @@ -332,6 +336,10 @@ In general this plugin provides: |Registers commercially licensed generic actions like per panel time range and contains some code that supports drilldown work. +|{kib-repo}blob/{branch}/src/plugins/unified_doc_viewer/README.md[unifiedDocViewer] +|This plugin contains services reliant on the plugin lifecycle for the unified doc viewer component (see @kbn/unified-doc-viewer). + + |{kib-repo}blob/{branch}/src/plugins/unified_histogram/README.md[unifiedHistogram] |Unified Histogram is a UX Building Block including a layout with a resizable histogram and a main display. It manages its own state and data fetching, and can easily be dropped into pages with minimal setup. @@ -516,14 +524,14 @@ Plugin server-side only. Plugin has three main functions: |Contains the enhancements to the OSS discover app. -|{kib-repo}blob/{branch}/x-pack/plugins/discover_log_explorer/README.md[discoverLogExplorer] -|This plugin registers a log-explorer profile using the Discover customization framework, offering several affordances specifically designed for log consumption. - - |{kib-repo}blob/{branch}/x-pack/plugins/ecs_data_quality_dashboard/README.md[ecsDataQualityDashboard] |This plugin implements (server) APIs used to render the content of the Data Quality dashboard. +|{kib-repo}blob/{branch}/x-pack/plugins/elastic_assistant/README.md[elasticAssistant] +|This plugin implements (only) server APIs for the Elastic AI Assistant. + + |<> |Enhances Embeddables by registering a custom factory provider. The enhanced factory provider adds dynamic actions to every embeddables state, in order to support drilldowns. @@ -624,6 +632,10 @@ the infrastructure monitoring use-case within Kibana. using the CURL scripts in the scripts folder. +|{kib-repo}blob/{branch}/x-pack/plugins/log_explorer/README.md[logExplorer] +|This plugin provides a LogExplorer component using the Discover customization framework, offering several affordances specifically designed for log consumption. + + |{kib-repo}blob/{branch}/x-pack/plugins/logs_shared/README.md[logsShared] |Exposes the shared components and APIs to access and visualize logs. @@ -661,6 +673,10 @@ Elastic. |This document gives an overview of the features of the Observability AI Assistant at the time of writing, and how to use them. At a high level, the Observability AI Assistant offers contextual insights, and a chat functionality that we enrich with function calling, allowing the LLM to hook into the user's data. We also allow the LLM to store things it considers new information as embeddings into Elasticsearch, and query this knowledge base when it decides it needs more information, using ELSER. +|{kib-repo}blob/{branch}/x-pack/plugins/observability_log_explorer/README.md[observabilityLogExplorer] +|This plugin provides an app based on the LogExplorer component from the log_explorer plugin, but adds observability-specific affordances. + + |{kib-repo}blob/{branch}/x-pack/plugins/observability_onboarding/README.md[observabilityOnboarding] |This plugin provides an onboarding framework for observability solutions: Logs and APM. @@ -681,6 +697,10 @@ Elastic. |Universal Profiling provides fleet-wide, whole-system, continuous profiling with zero instrumentation. Get a comprehensive understanding of what lines of code are consuming compute resources throughout your entire fleet by visualizing your data in Kibana using the flamegraph, stacktraces, and top functions views. +|{kib-repo}blob/{branch}/x-pack/plugins/profiling_data_access[profilingDataAccess] +|WARNING: Missing README. + + |{kib-repo}blob/{branch}/x-pack/plugins/remote_clusters/README.md[remoteClusters] |This plugin helps users manage their remote clusters, which enable cross-cluster search and cross-cluster replication. diff --git a/docs/developer/plugin/external-plugin-functional-tests.asciidoc b/docs/developer/plugin/external-plugin-functional-tests.asciidoc index 349602bb4f276..ff5a9b60d976d 100644 --- a/docs/developer/plugin/external-plugin-functional-tests.asciidoc +++ b/docs/developer/plugin/external-plugin-functional-tests.asciidoc @@ -80,5 +80,5 @@ node ../../kibana/scripts/functional_test_runner [discrete] === Using esArchiver -We're working on documentation for this, but for now the best place to look is the original {kib-repo}/issues/10359[pull request]. +We're working on documentation for this, but for now the best place to look is the original {kib-repo}issues/10359[pull request]. diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 5873af1ef9cb1..e0ddf9bd3f334 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -288,8 +288,8 @@ in the current data view is used. The columns that appear by default on the *Discover* page. The default is `_source`. -[[discover:enableSql]]`discover:enableSql`:: -experimental[] Allows SQL queries for search. +[[discover:enableESQL]]`discover:enableESQL`:: +experimental[] Allows ES|QL queries for search. [[discover-max-doc-fields-displayed]]`discover:maxDocFieldsDisplayed`:: Specifies the maximum number of fields to show in the document column of the *Discover* table. diff --git a/docs/management/connectors/action-types/server-log.asciidoc b/docs/management/connectors/action-types/server-log.asciidoc index 964d8300761a3..7399fb5456d45 100644 --- a/docs/management/connectors/action-types/server-log.asciidoc +++ b/docs/management/connectors/action-types/server-log.asciidoc @@ -3,13 +3,13 @@ ++++ Server log ++++ +:frontmatter-description: Add a connector that can write in {kib} server logs. +:frontmatter-tags-products: [kibana] +:frontmatter-tags-content-type: [how-to] +:frontmatter-tags-user-goals: [configure] A server log connector writes an entry to the {kib} server log. -You can create a server log connectors in {kib} or by using the -<>. If you are running {kib} -on-prem, you can also create preconfigured server log connectors. - [float] [[define-serverlog-ui]] === Create connectors in {kib} @@ -27,29 +27,12 @@ image::management/connectors/images/serverlog-connector.png[Server log connector Server log connectors do not have any configuration properties other than a name. -[float] -[[preconfigured-server-log-configuration]] -=== Create preconfigured connectors - -If you are running {kib} on-prem, you can define connectors by adding -`xpack.actions.preconfigured` settings to your `kibana.yml` file. For example: - -[source,text] --- -xpack.actions.preconfigured: - my-server-log: - name: preconfigured-server-log-connector-type - actionTypeId: .server-log --- - -For more information, go to <>. - [float] [[server-log-action-configuration]] === Test connectors -You can test connectors with the <> or -as you're creating or editing the connector in {kib}. For example: +You can test connectors as you're creating or editing the connector in {kib}. +For example: [role="screenshot"] image::management/connectors/images/serverlog-params-test.png[Server log connector test] diff --git a/docs/management/connectors/pre-configured-connectors.asciidoc b/docs/management/connectors/pre-configured-connectors.asciidoc index 9284a66ea9480..3584207a88364 100644 --- a/docs/management/connectors/pre-configured-connectors.asciidoc +++ b/docs/management/connectors/pre-configured-connectors.asciidoc @@ -80,9 +80,29 @@ image::images/preconfigured-connectors-managing.png[Connectors managing tab with Clicking a preconfigured connector shows the description, but not the configuration. +[float] +=== Examples + +* <> +* <> + +[float] +[[preconfigured-server-log-configuration]] +==== Server log connectors + +The following example creates a <>: + +[source,text] +-- +xpack.actions.preconfigured: + my-server-log: + name: preconfigured-server-log-connector-type + actionTypeId: .server-log +-- + [float] [[preconfigured-webhook-configuration]] -=== Webhook preconfigured connector example +==== Webhook connectors The following example creates a <> with basic authentication: diff --git a/docs/settings/alert-action-settings.asciidoc b/docs/settings/alert-action-settings.asciidoc index 692b309191b02..c48483224ec52 100644 --- a/docs/settings/alert-action-settings.asciidoc +++ b/docs/settings/alert-action-settings.asciidoc @@ -142,12 +142,6 @@ A list of action types that are enabled. It defaults to `["*"]`, enabling all ty + Disabled action types will not appear as an option when creating new connectors, but existing connectors and actions of that type will remain in {kib} and will not function. -`xpack.actions.preconfiguredAlertHistoryEsIndex` {ess-icon}:: -Enables a preconfigured alert history {es} <> connector. Default: `false`. - -`xpack.actions.preconfigured`:: -Specifies preconfigured connector IDs and configs. Default: {}. - `xpack.actions.proxyUrl` {ess-icon}:: Specifies the proxy URL to use, if using a proxy for actions. By default, no proxy is used. + @@ -166,10 +160,26 @@ curl --verbose --proxytunnel --proxy http://localhost:8080 http://example.com -- `xpack.actions.proxyBypassHosts` {ess-icon}:: -Specifies hostnames which should not use the proxy, if using a proxy for actions. The value is an array of hostnames as strings. By default, all hosts will use the proxy, but if an action's hostname is in this list, the proxy will not be used. The settings `xpack.actions.proxyBypassHosts` and `xpack.actions.proxyOnlyHosts` cannot be used at the same time. +Specifies hostnames which should not use the proxy, if using a proxy for actions. The value is an array of hostnames as strings. Example: ++ +[source,yaml] +---- +# If applicable, include the subdomain in the hostname +xpack.actions.proxyBypassHosts: [ "events.pagerduty.com" ] +---- ++ +By default, all hosts will use the proxy, but if an action's hostname is in this list, the proxy will not be used. The settings `xpack.actions.proxyBypassHosts` and `xpack.actions.proxyOnlyHosts` cannot be used at the same time. `xpack.actions.proxyOnlyHosts` {ess-icon}:: -Specifies hostnames which should only use the proxy, if using a proxy for actions. The value is an array of hostnames as strings. By default, no hosts will use the proxy, but if an action's hostname is in this list, the proxy will be used. The settings `xpack.actions.proxyBypassHosts` and `xpack.actions.proxyOnlyHosts` cannot be used at the same time. +Specifies hostnames which should only use the proxy, if using a proxy for actions. The value is an array of hostnames as strings. Example: ++ +[source,yaml] +---- +# If applicable, include the subdomain in the hostname +xpack.actions.proxyOnlyHosts: [ "events.pagerduty.com" ] +---- ++ +By default, no hosts will use the proxy, but if an action's hostname is in this list, the proxy will be used. The settings `xpack.actions.proxyBypassHosts` and `xpack.actions.proxyOnlyHosts` cannot be used at the same time. `xpack.actions.proxyHeaders` {ess-icon}:: Specifies HTTP headers for the proxy, if using a proxy for actions. Default: {}. @@ -217,6 +227,34 @@ xpack.actions.run: maxAttempts: 5 -- +[float] +[[preconfigured-connector-settings]] +=== Preconfigured connector settings + +These settings vary depending on which type of <> you're adding. +For example: + +[source,yaml] +---------------------------------------- +xpack.actions.preconfigured: + my-server-log: + name: preconfigured-server-log-connector-type + actionTypeId: .server-log +---------------------------------------- + +`xpack.actions.preconfiguredAlertHistoryEsIndex` {ess-icon}:: +Enables a preconfigured alert history {es} <> connector. Default: `false`. + +`xpack.actions.preconfigured`:: +Specifies configuration details that are specific to the type of preconfigured connector. + +`xpack.actions.preconfigured..actionTypeId`:: +The type of preconfigured connector. +For example: `.email`, `.index`, `.opsgenie`, `.server-log`, `.resilient`, `.slack`, and `.webhook`. + +`xpack.actions.preconfigured..name`:: +The name of the preconfigured connector. + [float] [[alert-settings]] === Alerting settings diff --git a/docs/user/production-considerations/production.asciidoc b/docs/user/production-considerations/production.asciidoc index 92cb77cc401f7..e0878b4dbf849 100644 --- a/docs/user/production-considerations/production.asciidoc +++ b/docs/user/production-considerations/production.asciidoc @@ -118,3 +118,12 @@ The option accepts a limit in MB: -------- --max-old-space-size=2048 -------- + +[float] +[[openssl-legacy-provider]] +=== OpenSSL Legacy Provider + +Starting in 8.10.0, {kib} has upgraded its runtime environment, Node.js, from version 16 to version 18 and with it the underlying version of OpenSSL to version 3. +Algorithms deemed legacy by OpenSSL 3 have been re-enabled to avoid potential breaking changes in a minor version release of {kib}. +If SSL certificates configured for {kib} are not using any of the legacy algorithms mentioned in the https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html[OpenSSL legacy provider documentation], +we recommend disabling this setting by removing `--openssl-legacy-provider` in the `node.options` config file. diff --git a/docs/user/security/authorization/index.asciidoc b/docs/user/security/authorization/index.asciidoc index 7127ebf84ae9b..d510508da63e8 100644 --- a/docs/user/security/authorization/index.asciidoc +++ b/docs/user/security/authorization/index.asciidoc @@ -75,6 +75,26 @@ NOTE: {kib} automatically surrounds your DLS query with a `query` block, so you [role="screenshot"] image::security/images/create-role-dls-example.png[Create role with DLS index privileges] +[[adding_remote_index_privileges]] +==== Remote index privileges + +If you have at least a platinum license, you can manage access to indices in remote clusters. + +You can assign the same privileges, document-level, and field-level as for <>. + +[[remote_index_privilege_example_1]] +===== Example: Grant access to indices in remote clusters + +. Go to **Stack Management > Roles**, and then click **Create role**. +. In **Remote index privileges**, enter: +.. The name of your remote cluster in the **Remote clusters** field. +.. The name of the index in your remote cluster in the **Remote indices** field. +.. The allowed actions in the **Privileges** field. (e.g. `read` and `view_index_metadata`) + +[role="screenshot"] +image::security/images/create-role-remote-index-example.png[Create role with remote index privileges] + + [[adding_kibana_privileges]] ==== {kib} privileges diff --git a/docs/user/security/images/create-role-dls-example.png b/docs/user/security/images/create-role-dls-example.png index 02b91ccf8820e..0899fce010146 100644 Binary files a/docs/user/security/images/create-role-dls-example.png and b/docs/user/security/images/create-role-dls-example.png differ diff --git a/docs/user/security/images/create-role-index-example.png b/docs/user/security/images/create-role-index-example.png index 8f95a74194274..68c833b244525 100644 Binary files a/docs/user/security/images/create-role-index-example.png and b/docs/user/security/images/create-role-index-example.png differ diff --git a/docs/user/security/images/create-role-remote-index-example.png b/docs/user/security/images/create-role-remote-index-example.png new file mode 100644 index 0000000000000..8008c8efd65c6 Binary files /dev/null and b/docs/user/security/images/create-role-remote-index-example.png differ diff --git a/docs/user/security/securing-kibana.asciidoc b/docs/user/security/securing-kibana.asciidoc index 875830ab88b46..98290bb093e41 100644 --- a/docs/user/security/securing-kibana.asciidoc +++ b/docs/user/security/securing-kibana.asciidoc @@ -27,7 +27,7 @@ configure additional security settings and authentication. . Set the `xpack.security.encryptionKey` property in the `kibana.yml` configuration file. You can use any text string that is 32 characters or longer -as the encryption key. +as the encryption key. Refer to <>. + -- [source,yaml] @@ -35,7 +35,10 @@ as the encryption key. xpack.security.encryptionKey: "something_at_least_32_characters" ---- -For more information, see <>. +{kib}'s reporting and saved objects features also have encryption key settings. +Refer to <> and +<> +respectively. -- . Optional: <>. diff --git a/examples/search_examples/public/search/app.tsx b/examples/search_examples/public/search/app.tsx index e6aeeaae648bd..0fa13df35a4e9 100644 --- a/examples/search_examples/public/search/app.tsx +++ b/examples/search_examples/public/search/app.tsx @@ -30,7 +30,6 @@ import { DataPublicPluginStart, IKibanaSearchResponse, isCompleteResponse, - isErrorResponse, } from '@kbn/data-plugin/public'; import { SearchResponseWarning } from '@kbn/data-plugin/public/search/types'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; @@ -247,9 +246,6 @@ export const SearchExamplesApp = ({ text: toMountPoint(res.warning), }); } - } else if (isErrorResponse(res)) { - // TODO: Make response error status clearer - notifications.toasts.addDanger('An error has occurred'); } }, error: (e) => { @@ -401,10 +397,6 @@ export const SearchExamplesApp = ({ title: 'Query result', text: 'Query finished', }); - } else if (isErrorResponse(res)) { - setIsLoading(false); - // TODO: Make response error status clearer - notifications.toasts.addWarning('An error has occurred'); } }, error: (e) => { diff --git a/examples/search_examples/public/search_sessions/app.tsx b/examples/search_examples/public/search_sessions/app.tsx index 701665fd52075..8b7c7bbcaa144 100644 --- a/examples/search_examples/public/search_sessions/app.tsx +++ b/examples/search_examples/public/search_sessions/app.tsx @@ -40,7 +40,6 @@ import { IEsSearchRequest, IEsSearchResponse, isCompleteResponse, - isErrorResponse, QueryState, SearchSessionState, } from '@kbn/data-plugin/public'; @@ -724,8 +723,6 @@ function doSearch( title: 'Query result', text: mountReactNode(message), }); - } else if (isErrorResponse(res)) { - notifications.toasts.addWarning('An error has occurred'); } }), map((res) => ({ response: res, request: req, tookMs: performance.now() - startTs })), diff --git a/examples/search_examples/public/sql_search/app.tsx b/examples/search_examples/public/sql_search/app.tsx index f8278736e4a70..33406a53f9674 100644 --- a/examples/search_examples/public/sql_search/app.tsx +++ b/examples/search_examples/public/sql_search/app.tsx @@ -27,7 +27,6 @@ import { DataPublicPluginStart, IKibanaSearchResponse, isCompleteResponse, - isErrorResponse, } from '@kbn/data-plugin/public'; import { SQL_SEARCH_STRATEGY, @@ -70,10 +69,6 @@ export const SqlSearchExampleApp = ({ notifications, data }: SearchExamplesAppDe if (isCompleteResponse(res)) { setIsLoading(false); setResponse(res); - } else if (isErrorResponse(res)) { - setIsLoading(false); - setResponse(res); - notifications.toasts.addDanger('An error has occurred'); } }, error: (e) => { diff --git a/examples/unified_doc_viewer/README.md b/examples/unified_doc_viewer/README.md new file mode 100644 index 0000000000000..fea17c5e9cde8 --- /dev/null +++ b/examples/unified_doc_viewer/README.md @@ -0,0 +1,3 @@ +## Unified Doc Viewer + +An example plugin showing usage of the unified doc viewer plugin (plugins/unified_doc_viewer) and package (@kbn/unified-doc-viewer). \ No newline at end of file diff --git a/examples/unified_doc_viewer/kibana.jsonc b/examples/unified_doc_viewer/kibana.jsonc new file mode 100644 index 0000000000000..6d9c4465072c6 --- /dev/null +++ b/examples/unified_doc_viewer/kibana.jsonc @@ -0,0 +1,16 @@ +{ + "type": "plugin", + "id": "@kbn/unified-doc-viewer-examples", + "owner": "@elastic/kibana-core", + "description": "Examples showing usage of the unified doc viewer.", + "plugin": { + "id": "unifiedDocViewerExamples", + "server": false, + "browser": true, + "requiredPlugins": [ + "data", + "developerExamples", + "unifiedDocViewer" + ] + } +} diff --git a/examples/unified_doc_viewer/public/application.tsx b/examples/unified_doc_viewer/public/application.tsx new file mode 100644 index 0000000000000..11cf99e1ed2bb --- /dev/null +++ b/examples/unified_doc_viewer/public/application.tsx @@ -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 React, { useEffect, useState } from 'react'; +import ReactDOM from 'react-dom'; +import type { AppMountParameters, CoreStart } from '@kbn/core/public'; +import { buildDataTableRecord } from '@kbn/discover-utils'; +import type { DataTableRecord } from '@kbn/discover-utils/types'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import { UnifiedDocViewer } from '@kbn/unified-doc-viewer-plugin/public'; +import { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { StartDeps } from './plugin'; + +export const renderApp = ( + core: CoreStart, + { data }: StartDeps, + { element }: AppMountParameters +) => { + ReactDOM.render(, element); + + return () => { + ReactDOM.unmountComponentAtNode(element); + }; +}; + +function UnifiedDocViewerExamplesApp({ data }: { data: DataPublicPluginStart }) { + const [dataView, setDataView] = useState(); + const [hit, setHit] = useState(); + + useEffect(() => { + data.dataViews.getDefault().then((defaultDataView) => setDataView(defaultDataView)); + }, [data]); + + useEffect(() => { + const setDefaultHit = async () => { + if (!dataView?.id) return; + const response = await data.search + .search({ + params: { + index: dataView?.getIndexPattern(), + body: { + fields: ['*'], + _source: false, + }, + }, + }) + .toPromise(); + const docs = response?.rawResponse?.hits?.hits ?? []; + if (docs.length > 0) { + const record = buildDataTableRecord(docs[0], dataView); + setHit(record); + } + }; + + setDefaultHit(); + }, [data, dataView]); + + return ( + <> + {dataView?.id && hit ? ( + + ) : ( + 'Loading... (make sure you have a default data view and at least one matching document)' + )} + + ); +} diff --git a/examples/unified_doc_viewer/public/index.ts b/examples/unified_doc_viewer/public/index.ts new file mode 100644 index 0000000000000..98580e69ded6e --- /dev/null +++ b/examples/unified_doc_viewer/public/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { UnifiedDocViewerExamplesPlugin } from './plugin'; + +export function plugin() { + return new UnifiedDocViewerExamplesPlugin(); +} diff --git a/examples/unified_doc_viewer/public/plugin.tsx b/examples/unified_doc_viewer/public/plugin.tsx new file mode 100644 index 0000000000000..d12c746a06223 --- /dev/null +++ b/examples/unified_doc_viewer/public/plugin.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 and the Server Side Public License, v 1; you may 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 { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; +import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; + +export interface SetupDeps { + developerExamples: DeveloperExamplesSetup; +} + +export interface StartDeps { + data: DataPublicPluginStart; +} + +export class UnifiedDocViewerExamplesPlugin implements Plugin { + public setup(core: CoreSetup, deps: SetupDeps) { + // Register an application into the side navigation menu + core.application.register({ + id: 'unifiedDocViewer', + title: 'Unified Doc Viewer Examples', + async mount(params: AppMountParameters) { + // Load application bundle + const { renderApp } = await import('./application'); + // Get start services as specified in kibana.json + const [coreStart, depsStart] = await core.getStartServices(); + // Render the application + return renderApp(coreStart, depsStart, params); + }, + }); + + // This section is only needed to get this example plugin to show up in our Developer Examples. + deps.developerExamples.register({ + appId: 'unifiedDocViewer', + title: 'Unified Doc Viewer Examples', + description: 'Examples showcasing the unified doc viewer.', + }); + } + + public start(core: CoreStart) { + return {}; + } + + public stop() {} +} diff --git a/examples/unified_doc_viewer/tsconfig.json b/examples/unified_doc_viewer/tsconfig.json new file mode 100644 index 0000000000000..74f81731edbe8 --- /dev/null +++ b/examples/unified_doc_viewer/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types" + }, + "include": [ + "index.ts", + "common/**/*.ts", + "public/**/*.ts", + "public/**/*.tsx", + "../../typings/**/*" + ], + "exclude": [ + "target/**/*", + ], + "kbn_references": [ + "@kbn/core", + "@kbn/data-plugin", + "@kbn/data-views-plugin", + "@kbn/developer-examples-plugin", + "@kbn/discover-utils", + "@kbn/unified-doc-viewer-plugin", + ] +} diff --git a/fleet_packages.json b/fleet_packages.json index e902be45dda44..5ad9b3cff5830 100644 --- a/fleet_packages.json +++ b/fleet_packages.json @@ -24,13 +24,13 @@ [ { "name": "apm", - "version": "8.11.0-preview-1692605695", + "version": "8.11.0-preview-1693211748", "forceAlignStackVersion": true, "allowSyncToPrerelease": true }, { "name": "elastic_agent", - "version": "1.11.2" + "version": "1.12.0" }, { "name": "endpoint", diff --git a/package.json b/package.json index ed15195079ffc..86071279c1ce4 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "dependencies": { "@appland/sql-parser": "^1.5.1", "@babel/runtime": "^7.21.0", + "@cfworker/json-schema": "^1.12.7", "@dnd-kit/core": "^3.1.1", "@dnd-kit/sortable": "^4.0.0", "@dnd-kit/utilities": "^2.0.0", @@ -373,7 +374,6 @@ "@kbn/developer-examples-plugin": "link:examples/developer_examples", "@kbn/discover-customization-examples-plugin": "link:examples/discover_customization_examples", "@kbn/discover-enhanced-plugin": "link:x-pack/plugins/discover_enhanced", - "@kbn/discover-log-explorer-plugin": "link:x-pack/plugins/discover_log_explorer", "@kbn/discover-plugin": "link:src/plugins/discover", "@kbn/discover-utils": "link:packages/kbn-discover-utils", "@kbn/doc-links": "link:packages/kbn-doc-links", @@ -383,6 +383,7 @@ "@kbn/ecs-data-quality-dashboard": "link:x-pack/packages/security-solution/ecs_data_quality_dashboard", "@kbn/ecs-data-quality-dashboard-plugin": "link:x-pack/plugins/ecs_data_quality_dashboard", "@kbn/elastic-assistant": "link:x-pack/packages/kbn-elastic-assistant", + "@kbn/elastic-assistant-plugin": "link:x-pack/plugins/elastic_assistant", "@kbn/elasticsearch-client-plugin": "link:test/plugin_functional/plugins/elasticsearch_client_plugin", "@kbn/elasticsearch-client-xpack-plugin": "link:x-pack/test/plugin_api_integration/plugins/elasticsearch_client", "@kbn/embeddable-enhanced-plugin": "link:x-pack/plugins/embeddable_enhanced", @@ -492,6 +493,7 @@ "@kbn/lists-plugin": "link:x-pack/plugins/lists", "@kbn/locator-examples-plugin": "link:examples/locator_examples", "@kbn/locator-explorer-plugin": "link:examples/locator_explorer", + "@kbn/log-explorer-plugin": "link:x-pack/plugins/log_explorer", "@kbn/logging": "link:packages/kbn-logging", "@kbn/logging-mocks": "link:packages/kbn-logging-mocks", "@kbn/logs-shared-plugin": "link:x-pack/plugins/logs_shared", @@ -535,11 +537,13 @@ "@kbn/navigation-plugin": "link:src/plugins/navigation", "@kbn/newsfeed-plugin": "link:src/plugins/newsfeed", "@kbn/newsfeed-test-plugin": "link:test/common/plugins/newsfeed", + "@kbn/no-data-page-plugin": "link:src/plugins/no_data_page", "@kbn/notifications-plugin": "link:x-pack/plugins/notifications", "@kbn/object-versioning": "link:packages/kbn-object-versioning", "@kbn/observability-ai-assistant-plugin": "link:x-pack/plugins/observability_ai_assistant", "@kbn/observability-alert-details": "link:x-pack/packages/observability/alert_details", "@kbn/observability-fixtures-plugin": "link:x-pack/test/cases_api_integration/common/plugins/observability", + "@kbn/observability-log-explorer-plugin": "link:x-pack/plugins/observability_log_explorer", "@kbn/observability-onboarding-plugin": "link:x-pack/plugins/observability_onboarding", "@kbn/observability-plugin": "link:x-pack/plugins/observability", "@kbn/observability-shared-plugin": "link:x-pack/plugins/observability_shared", @@ -552,6 +556,7 @@ "@kbn/portable-dashboards-example": "link:examples/portable_dashboards_example", "@kbn/preboot-example-plugin": "link:examples/preboot_example", "@kbn/presentation-util-plugin": "link:src/plugins/presentation_util", + "@kbn/profiling-data-access-plugin": "link:x-pack/plugins/profiling_data_access", "@kbn/profiling-plugin": "link:x-pack/plugins/profiling", "@kbn/random-sampling": "link:x-pack/packages/kbn-random-sampling", "@kbn/react-field": "link:packages/kbn-react-field", @@ -602,6 +607,7 @@ "@kbn/searchprofiler-plugin": "link:x-pack/plugins/searchprofiler", "@kbn/security-plugin": "link:x-pack/plugins/security", "@kbn/security-solution-ess": "link:x-pack/plugins/security_solution_ess", + "@kbn/security-solution-features": "link:x-pack/packages/security-solution/features", "@kbn/security-solution-fixtures-plugin": "link:x-pack/test/cases_api_integration/common/plugins/security_solution", "@kbn/security-solution-navigation": "link:x-pack/packages/security-solution/navigation", "@kbn/security-solution-plugin": "link:x-pack/plugins/security_solution", @@ -737,6 +743,10 @@ "@kbn/ui-shared-deps-npm": "link:packages/kbn-ui-shared-deps-npm", "@kbn/ui-shared-deps-src": "link:packages/kbn-ui-shared-deps-src", "@kbn/ui-theme": "link:packages/kbn-ui-theme", + "@kbn/unified-data-table": "link:packages/kbn-unified-data-table", + "@kbn/unified-doc-viewer": "link:packages/kbn-unified-doc-viewer", + "@kbn/unified-doc-viewer-examples": "link:examples/unified_doc_viewer", + "@kbn/unified-doc-viewer-plugin": "link:src/plugins/unified_doc_viewer", "@kbn/unified-field-list": "link:packages/kbn-unified-field-list", "@kbn/unified-field-list-examples-plugin": "link:examples/unified_field_list_examples", "@kbn/unified-histogram-plugin": "link:src/plugins/unified_histogram", @@ -806,6 +816,7 @@ "JSONStream": "1.3.5", "adm-zip": "^0.5.9", "ajv": "^8.12.0", + "ansi-regex": "^5.0.1", "antlr4ts": "^0.5.0-alpha.3", "archiver": "^5.3.1", "async": "^3.2.3", @@ -895,6 +906,7 @@ "jsonwebtoken": "^9.0.0", "jsts": "^1.6.2", "kea": "^2.4.2", + "langchain": "^0.0.132", "launchdarkly-js-client-sdk": "^2.22.1", "launchdarkly-node-server-sdk": "^6.4.2", "load-json-file": "^6.2.0", @@ -1002,6 +1014,7 @@ "suricata-sid-db": "^1.0.2", "symbol-observable": "^1.2.0", "tar": "^6.1.15", + "textarea-caret": "^3.1.0", "tinycolor2": "1.4.1", "tinygradient": "0.4.3", "ts-easing": "^0.2.0", @@ -1363,6 +1376,7 @@ "@types/tar": "^6.1.5", "@types/tempy": "^0.2.0", "@types/testing-library__jest-dom": "^5.14.7", + "@types/textarea-caret": "^3.0.1", "@types/tinycolor2": "^1.4.1", "@types/tough-cookie": "^4.0.2", "@types/type-detect": "^4.0.1", @@ -1557,6 +1571,7 @@ "val-loader": "^1.1.1", "vinyl-fs": "^4.0.0", "watchpack": "^1.6.0", + "web-streams-polyfill": "^3.2.1", "webpack": "^4.41.5", "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "^4.10.0", diff --git a/packages/core/apps/core-apps-server-internal/index.ts b/packages/core/apps/core-apps-server-internal/index.ts index 7a28e9f9d2f87..3fe3261446dbc 100644 --- a/packages/core/apps/core-apps-server-internal/index.ts +++ b/packages/core/apps/core-apps-server-internal/index.ts @@ -6,8 +6,9 @@ * Side Public License, v 1. */ -export { CoreAppsService } from './src'; +export { CoreAppsService, config } from './src'; export type { + CoreAppConfigType, InternalCoreAppsServiceRequestHandlerContext, InternalCoreAppsServiceRouter, } from './src'; diff --git a/packages/core/apps/core-apps-server-internal/src/core_app.test.ts b/packages/core/apps/core-apps-server-internal/src/core_app.test.ts index 13122b4b09eb7..f16abb781bbfb 100644 --- a/packages/core/apps/core-apps-server-internal/src/core_app.test.ts +++ b/packages/core/apps/core-apps-server-internal/src/core_app.test.ts @@ -17,6 +17,7 @@ import { PluginType } from '@kbn/core-base-common'; import type { RequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; import { coreInternalLifecycleMock } from '@kbn/core-lifecycle-server-mocks'; import { CoreAppsService } from './core_app'; +import { of } from 'rxjs'; const emptyPlugins = (): UiPlugins => ({ internal: new Map(), @@ -56,10 +57,43 @@ describe('CoreApp', () => { registerBundleRoutesMock.mockReset(); }); + describe('`/internal/core/_settings` route', () => { + it('is not registered by default', async () => { + const routerMock = mockRouter.create(); + internalCoreSetup.http.createRouter.mockReturnValue(routerMock); + + const localCoreApp = new CoreAppsService(coreContext); + await localCoreApp.setup(internalCoreSetup, emptyPlugins()); + + expect(routerMock.versioned.put).not.toHaveBeenCalledWith( + expect.objectContaining({ + path: '/internal/core/_settings', + }) + ); + }); + + it('is registered when enabled', async () => { + const routerMock = mockRouter.create(); + internalCoreSetup.http.createRouter.mockReturnValue(routerMock); + + coreContext.configService.atPath.mockReturnValue(of({ allowDynamicConfigOverrides: true })); + const localCoreApp = new CoreAppsService(coreContext); + await localCoreApp.setup(internalCoreSetup, emptyPlugins()); + + expect(routerMock.versioned.put).toHaveBeenCalledWith({ + path: '/internal/core/_settings', + access: 'internal', + options: { + tags: ['access:updateDynamicConfig'], + }, + }); + }); + }); + describe('`/status` route', () => { - it('is registered with `authRequired: false` is the status page is anonymous', () => { + it('is registered with `authRequired: false` is the status page is anonymous', async () => { internalCoreSetup.status.isStatusPageAnonymous.mockReturnValue(true); - coreApp.setup(internalCoreSetup, emptyPlugins()); + await coreApp.setup(internalCoreSetup, emptyPlugins()); expect(httpResourcesRegistrar.register).toHaveBeenCalledWith( { @@ -73,9 +107,9 @@ describe('CoreApp', () => { ); }); - it('is registered with `authRequired: true` is the status page is not anonymous', () => { + it('is registered with `authRequired: true` is the status page is not anonymous', async () => { internalCoreSetup.status.isStatusPageAnonymous.mockReturnValue(false); - coreApp.setup(internalCoreSetup, emptyPlugins()); + await coreApp.setup(internalCoreSetup, emptyPlugins()); expect(httpResourcesRegistrar.register).toHaveBeenCalledWith( { @@ -185,8 +219,8 @@ describe('CoreApp', () => { }); describe('`/app/{id}/{any*}` route', () => { - it('is registered with the correct parameters', () => { - coreApp.setup(internalCoreSetup, emptyPlugins()); + it('is registered with the correct parameters', async () => { + await coreApp.setup(internalCoreSetup, emptyPlugins()); expect(httpResourcesRegistrar.register).toHaveBeenCalledWith( { @@ -201,9 +235,9 @@ describe('CoreApp', () => { }); }); - it('`setup` calls `registerBundleRoutes` with the correct options', () => { + it('`setup` calls `registerBundleRoutes` with the correct options', async () => { const uiPlugins = emptyPlugins(); - coreApp.setup(internalCoreSetup, uiPlugins); + await coreApp.setup(internalCoreSetup, uiPlugins); expect(registerBundleRoutesMock).toHaveBeenCalledTimes(1); expect(registerBundleRoutesMock).toHaveBeenCalledWith({ diff --git a/packages/core/apps/core-apps-server-internal/src/core_app.ts b/packages/core/apps/core-apps-server-internal/src/core_app.ts index 6ef61c8571c6f..4d303d24d37a1 100644 --- a/packages/core/apps/core-apps-server-internal/src/core_app.ts +++ b/packages/core/apps/core-apps-server-internal/src/core_app.ts @@ -7,8 +7,8 @@ */ import { stringify } from 'querystring'; -import { Env } from '@kbn/config'; -import { schema } from '@kbn/config-schema'; +import { Env, IConfigService } from '@kbn/config'; +import { schema, ValidationError } from '@kbn/config-schema'; import { fromRoot } from '@kbn/repo-info'; import type { Logger } from '@kbn/logging'; import type { CoreContext } from '@kbn/core-base-server-internal'; @@ -22,6 +22,8 @@ import type { import type { UiPlugins } from '@kbn/core-plugins-base-server-internal'; import type { HttpResources, HttpResourcesServiceToolkit } from '@kbn/core-http-resources-server'; import type { InternalCorePreboot, InternalCoreSetup } from '@kbn/core-lifecycle-server-internal'; +import { firstValueFrom, map, type Observable } from 'rxjs'; +import { CoreAppConfig, type CoreAppConfigType, CoreAppPath } from './core_app_config'; import { registerBundleRoutes } from './bundle_routes'; import type { InternalCoreAppsServiceRequestHandlerContext } from './internal_types'; @@ -41,10 +43,16 @@ interface CommonRoutesParams { export class CoreAppsService { private readonly logger: Logger; private readonly env: Env; + private readonly configService: IConfigService; + private readonly config$: Observable; constructor(core: CoreContext) { this.logger = core.logger.get('core-app'); this.env = core.env; + this.configService = core.configService; + this.config$ = this.configService + .atPath(CoreAppPath) + .pipe(map((rawCfg) => new CoreAppConfig(rawCfg))); } preboot(corePreboot: InternalCorePreboot, uiPlugins: UiPlugins) { @@ -57,9 +65,10 @@ export class CoreAppsService { } } - setup(coreSetup: InternalCoreSetup, uiPlugins: UiPlugins) { + async setup(coreSetup: InternalCoreSetup, uiPlugins: UiPlugins) { this.logger.debug('Setting up core app.'); - this.registerDefaultRoutes(coreSetup, uiPlugins); + const config = await firstValueFrom(this.config$); + this.registerDefaultRoutes(coreSetup, uiPlugins, config); this.registerStaticDirs(coreSetup); } @@ -88,7 +97,11 @@ export class CoreAppsService { }); } - private registerDefaultRoutes(coreSetup: InternalCoreSetup, uiPlugins: UiPlugins) { + private registerDefaultRoutes( + coreSetup: InternalCoreSetup, + uiPlugins: UiPlugins, + config: CoreAppConfig + ) { const httpSetup = coreSetup.http; const router = httpSetup.createRouter(''); const resources = coreSetup.httpResources.createRegistrar(router); @@ -147,6 +160,51 @@ export class CoreAppsService { } } ); + + if (config.allowDynamicConfigOverrides) { + this.registerInternalCoreSettingsRoute(router); + } + } + + /** + * Registers the HTTP API that allows updating in-memory the settings that opted-in to be dynamically updatable. + * @param router {@link IRouter} + * @private + */ + private registerInternalCoreSettingsRoute(router: IRouter) { + router.versioned + .put({ + path: '/internal/core/_settings', + access: 'internal', + options: { + tags: ['access:updateDynamicConfig'], + }, + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: schema.recordOf(schema.string(), schema.any()), + }, + response: { + '200': { body: schema.object({ ok: schema.boolean() }) }, + }, + }, + }, + async (context, req, res) => { + try { + this.configService.setDynamicConfigOverrides(req.body); + } catch (err) { + if (err instanceof ValidationError) { + return res.badRequest({ body: err }); + } + throw err; + } + + return res.ok({ body: { ok: true } }); + } + ); } private registerCommonDefaultRoutes({ diff --git a/packages/core/apps/core-apps-server-internal/src/core_app_config.test.ts b/packages/core/apps/core-apps-server-internal/src/core_app_config.test.ts new file mode 100644 index 0000000000000..2ac60e19fd637 --- /dev/null +++ b/packages/core/apps/core-apps-server-internal/src/core_app_config.test.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { config, CoreAppConfig } from './core_app_config'; + +describe('CoreApp Config', () => { + test('set correct defaults', () => { + const configValue = new CoreAppConfig(config.schema.validate({})); + expect(configValue).toMatchInlineSnapshot(` + CoreAppConfig { + "allowDynamicConfigOverrides": false, + } + `); + }); +}); diff --git a/packages/core/apps/core-apps-server-internal/src/core_app_config.ts b/packages/core/apps/core-apps-server-internal/src/core_app_config.ts new file mode 100644 index 0000000000000..d98a053433683 --- /dev/null +++ b/packages/core/apps/core-apps-server-internal/src/core_app_config.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 { schema, type TypeOf } from '@kbn/config-schema'; +import type { ServiceConfigDescriptor } from '@kbn/core-base-server-internal'; + +/** + * Validation schema for Core App config. + * @public + */ +export const configSchema = schema.object({ + allowDynamicConfigOverrides: schema.boolean({ defaultValue: false }), +}); + +export type CoreAppConfigType = TypeOf; + +export const CoreAppPath = 'coreApp'; + +export const config: ServiceConfigDescriptor = { + path: CoreAppPath, + schema: configSchema, +}; + +/** + * Wrapper of config schema. + * @internal + */ +export class CoreAppConfig implements CoreAppConfigType { + /** + * @internal + * When true, the HTTP API to dynamically extend the configuration is registered. + * + * @remarks + * You should enable this at your own risk: Settings opted-in to being dynamically + * configurable can be changed at any given point, potentially leading to unexpected behaviours. + * This feature is mostly intended for testing purposes. + */ + public readonly allowDynamicConfigOverrides: boolean; + + constructor(rawConfig: CoreAppConfig) { + this.allowDynamicConfigOverrides = rawConfig.allowDynamicConfigOverrides; + } +} diff --git a/packages/core/apps/core-apps-server-internal/src/index.ts b/packages/core/apps/core-apps-server-internal/src/index.ts index d2eca9036f40e..2792538f5f2ba 100644 --- a/packages/core/apps/core-apps-server-internal/src/index.ts +++ b/packages/core/apps/core-apps-server-internal/src/index.ts @@ -7,6 +7,7 @@ */ export { CoreAppsService } from './core_app'; +export { config, type CoreAppConfigType } from './core_app_config'; export type { InternalCoreAppsServiceRequestHandlerContext, InternalCoreAppsServiceRouter, diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/index.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/index.ts index 48b54addb7d95..3d81cebf9dc85 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/index.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/index.ts @@ -29,4 +29,5 @@ export { export { CoreElasticsearchRouteHandlerContext } from './src/elasticsearch_route_handler_context'; export { retryCallCluster, migrationRetryCallCluster } from './src/retry_call_cluster'; export { isInlineScriptingEnabled } from './src/is_scripting_enabled'; +export { getCapabilitiesFromClient } from './src/get_capabilities'; export type { ClusterInfo } from './src/get_cluster_info'; diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.test.mocks.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.test.mocks.ts index d04b7dfda2b3e..3be2c11d3f4b7 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.test.mocks.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.test.mocks.ts @@ -23,3 +23,8 @@ export const isScriptingEnabledMock = jest.fn(); jest.doMock('./is_scripting_enabled', () => ({ isInlineScriptingEnabled: isScriptingEnabledMock, })); + +export const getClusterInfoMock = jest.fn(); +jest.doMock('./get_cluster_info', () => ({ + getClusterInfo$: getClusterInfoMock, +})); diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.test.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.test.ts index a145da71fab83..c91db5dc8910c 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.test.ts @@ -16,10 +16,14 @@ jest.mock('./version_check/ensure_es_version', () => ({ pollEsNodesVersion: jest.fn(), })); -import { MockClusterClient, isScriptingEnabledMock } from './elasticsearch_service.test.mocks'; +import { + MockClusterClient, + isScriptingEnabledMock, + getClusterInfoMock, +} from './elasticsearch_service.test.mocks'; import type { NodesVersionCompatibility } from './version_check/ensure_es_version'; -import { BehaviorSubject, firstValueFrom } from 'rxjs'; +import { BehaviorSubject, firstValueFrom, of } from 'rxjs'; import { first, concatMap } from 'rxjs/operators'; import { REPO_ROOT } from '@kbn/repo-info'; import { Env } from '@kbn/config'; @@ -81,6 +85,8 @@ beforeEach(() => { isScriptingEnabledMock.mockResolvedValue(true); + getClusterInfoMock.mockReturnValue(of({})); + // @ts-expect-error TS does not get that `pollEsNodesVersion` is mocked pollEsNodesVersionMocked.mockImplementation(pollEsNodesVersionActual); }); @@ -89,6 +95,7 @@ afterEach(async () => { jest.clearAllMocks(); MockClusterClient.mockClear(); isScriptingEnabledMock.mockReset(); + getClusterInfoMock.mockReset(); await elasticsearchService?.stop(); }); diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.ts index c1396daf1aa66..38ee9acdfdaf0 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_service.ts @@ -21,6 +21,7 @@ import type { InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; import type { UnauthorizedErrorHandler, ElasticsearchClientConfig, + ElasticsearchCapabilities, } from '@kbn/core-elasticsearch-server'; import { ClusterClient, AgentManager } from '@kbn/core-elasticsearch-client-server-internal'; @@ -37,7 +38,8 @@ import { calculateStatus$ } from './status'; import { isValidConnection } from './is_valid_connection'; import { isInlineScriptingEnabled } from './is_scripting_enabled'; import { mergeConfig } from './merge_config'; -import { getClusterInfo$ } from './get_cluster_info'; +import { type ClusterInfo, getClusterInfo$ } from './get_cluster_info'; +import { getElasticsearchCapabilities } from './get_capabilities'; export interface SetupDeps { analytics: AnalyticsServiceSetup; @@ -57,6 +59,7 @@ export class ElasticsearchService private executionContextClient?: IExecutionContext; private esNodesCompatibility$?: Observable; private client?: ClusterClient; + private clusterInfo$?: Observable; private unauthorizedErrorHandler?: UnauthorizedErrorHandler; private agentManager: AgentManager; @@ -104,14 +107,14 @@ export class ElasticsearchService this.esNodesCompatibility$ = esNodesCompatibility$; - const clusterInfo$ = getClusterInfo$(this.client.asInternalUser); - registerAnalyticsContextProvider(deps.analytics, clusterInfo$); + this.clusterInfo$ = getClusterInfo$(this.client.asInternalUser); + registerAnalyticsContextProvider(deps.analytics, this.clusterInfo$); return { legacy: { config$: this.config$, }, - clusterInfo$, + clusterInfo$: this.clusterInfo$, esNodesCompatibility$, status$: calculateStatus$(esNodesCompatibility$), setUnauthorizedErrorHandler: (handler) => { @@ -140,6 +143,8 @@ export class ElasticsearchService } }); + let capabilities: ElasticsearchCapabilities; + if (!config.skipStartupConnectionCheck) { // Ensure that the connection is established and the product is valid before moving on await isValidConnection(this.esNodesCompatibility$); @@ -155,11 +160,21 @@ export class ElasticsearchService 'Refer to https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting-security.html for more info.' ); } + + capabilities = getElasticsearchCapabilities({ + clusterInfo: await firstValueFrom(this.clusterInfo$!), + }); + } else { + // skipStartupConnectionCheck is only used for unit testing, we default to base capabilities + capabilities = { + serverless: false, + }; } return { client: this.client!, createClient: (type, clientConfig) => this.createClusterClient(type, config, clientConfig), + getCapabilities: () => capabilities, }; } diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_capabilities.test.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_capabilities.test.ts new file mode 100644 index 0000000000000..4d01aa4e91807 --- /dev/null +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_capabilities.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { getElasticsearchCapabilities } from './get_capabilities'; +import type { ClusterInfo } from './get_cluster_info'; + +describe('getElasticsearchCapabilities', () => { + const getClusterInfo = (parts: Partial): ClusterInfo => ({ + cluster_name: 'cluster_name', + cluster_uuid: 'uuid', + cluster_version: '13.42.9000', + cluster_build_flavor: 'default', + ...parts, + }); + + describe('capabilities.serverless', () => { + it('is `true` when `build_flavor` is `serverless`', () => { + expect( + getElasticsearchCapabilities({ + clusterInfo: getClusterInfo({ cluster_build_flavor: 'serverless' }), + }) + ).toEqual( + expect.objectContaining({ + serverless: true, + }) + ); + }); + + it('is `false` when `build_flavor` is `default`', () => { + expect( + getElasticsearchCapabilities({ + clusterInfo: getClusterInfo({ cluster_build_flavor: 'default' }), + }) + ).toEqual( + expect.objectContaining({ + serverless: false, + }) + ); + }); + + it('is `false` when `build_flavor` is a random string', () => { + expect( + getElasticsearchCapabilities({ + clusterInfo: getClusterInfo({ cluster_build_flavor: 'some totally random string' }), + }) + ).toEqual( + expect.objectContaining({ + serverless: false, + }) + ); + }); + }); +}); diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_capabilities.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_capabilities.ts new file mode 100644 index 0000000000000..785ccc83d9619 --- /dev/null +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_capabilities.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { firstValueFrom } from 'rxjs'; +import type { + ElasticsearchCapabilities, + ElasticsearchClient, +} from '@kbn/core-elasticsearch-server'; +import { type ClusterInfo, getClusterInfo$ } from './get_cluster_info'; + +const SERVERLESS_BUILD_FLAVOR = 'serverless'; + +export const getElasticsearchCapabilities = ({ + clusterInfo, +}: { + clusterInfo: ClusterInfo; +}): ElasticsearchCapabilities => { + const buildFlavor = clusterInfo.cluster_build_flavor; + + return { + serverless: buildFlavor === SERVERLESS_BUILD_FLAVOR, + }; +}; + +/** + * Returns the capabilities for the ES cluster the provided client is connected to. + * + * @internal + */ +export const getCapabilitiesFromClient = async ( + client: ElasticsearchClient +): Promise => { + const clusterInfo = await firstValueFrom(getClusterInfo$(client)); + return getElasticsearchCapabilities({ clusterInfo }); +}; diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.test.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.test.ts index 100fac8e1197b..2bd8f2828544b 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.test.ts @@ -21,7 +21,7 @@ describe('getClusterInfo', () => { number: '1.2.3', lucene_version: '1.2.3', build_date: 'DateString', - build_flavor: 'string', + build_flavor: 'default', build_hash: 'string', build_snapshot: true, build_type: 'string', @@ -39,6 +39,7 @@ describe('getClusterInfo', () => { const context$ = getClusterInfo$(internalClient); await expect(firstValueFrom(context$)).resolves.toMatchInlineSnapshot(` Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster_uuid", "cluster_version": "1.2.3", @@ -52,6 +53,7 @@ describe('getClusterInfo', () => { const context$ = getClusterInfo$(internalClient); await expect(firstValueFrom(context$)).resolves.toMatchInlineSnapshot(` Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster_uuid", "cluster_version": "1.2.3", @@ -65,6 +67,7 @@ describe('getClusterInfo', () => { const context$ = getClusterInfo$(internalClient); await expect(firstValueFrom(context$)).resolves.toMatchInlineSnapshot(` Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster_uuid", "cluster_version": "1.2.3", @@ -72,6 +75,7 @@ describe('getClusterInfo', () => { `); await expect(firstValueFrom(context$)).resolves.toMatchInlineSnapshot(` Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster_uuid", "cluster_version": "1.2.3", diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.ts index 96ef87430048c..a11365feef739 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.ts @@ -15,6 +15,7 @@ export interface ClusterInfo { cluster_name: string; cluster_uuid: string; cluster_version: string; + cluster_build_flavor: string; } /** @@ -28,6 +29,7 @@ export function getClusterInfo$(internalClient: ElasticsearchClient): Observable cluster_name: info.cluster_name, cluster_uuid: info.cluster_uuid, cluster_version: info.version.number, + cluster_build_flavor: info.version.build_flavor, })), retry({ delay: 1000 }), shareReplay(1) diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.test.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.test.ts index b041586cf1903..057299c58165e 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.test.ts @@ -21,11 +21,17 @@ describe('registerAnalyticsContextProvider', () => { test('it provides the context', async () => { registerAnalyticsContextProvider( analyticsMock, - of({ cluster_name: 'cluster-name', cluster_uuid: 'cluster_uuid', cluster_version: '1.2.3' }) + of({ + cluster_name: 'cluster-name', + cluster_uuid: 'cluster_uuid', + cluster_version: '1.2.3', + cluster_build_flavor: 'default', + }) ); const { context$ } = analyticsMock.registerContextProvider.mock.calls[0][0]; await expect(firstValueFrom(context$)).resolves.toMatchInlineSnapshot(` Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster_uuid", "cluster_version": "1.2.3", diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.ts index 9120d48fcb606..be909f5ba21e5 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.ts @@ -27,6 +27,7 @@ export function registerAnalyticsContextProvider( cluster_name: { type: 'keyword', _meta: { description: 'The Cluster Name' } }, cluster_uuid: { type: 'keyword', _meta: { description: 'The Cluster UUID' } }, cluster_version: { type: 'keyword', _meta: { description: 'The Cluster version' } }, + cluster_build_flavor: { type: 'keyword', _meta: { description: 'The Cluster build flavor' } }, }, }); } diff --git a/packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts b/packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts index 4cfb3ecc45c32..88016464a2848 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts @@ -18,7 +18,9 @@ import { import type { ElasticsearchClientConfig, ElasticsearchServiceSetup, + ElasticsearchServiceStart, ElasticsearchServicePreboot, + ElasticsearchCapabilities, } from '@kbn/core-elasticsearch-server'; import type { ElasticsearchConfig, @@ -40,12 +42,14 @@ export type MockedElasticSearchServiceSetup = jest.Mocked< }; }; -export interface MockedElasticSearchServiceStart { +export type MockedElasticSearchServiceStart = jest.Mocked< + Omit +> & { client: ClusterClientMock; createClient: jest.MockedFunction< (type: string, config?: Partial) => CustomClusterClientMock >; -} +}; const createPrebootContractMock = () => { const prebootContract: MockedElasticSearchServicePreboot = { @@ -69,6 +73,7 @@ const createStartContractMock = () => { const startContract: MockedElasticSearchServiceStart = { client: elasticsearchClientMock.createClusterClient(), createClient: jest.fn((type: string) => elasticsearchClientMock.createCustomClusterClient()), + getCapabilities: jest.fn().mockReturnValue(createCapabilities()), }; return startContract; }; @@ -90,6 +95,7 @@ const createInternalSetupContractMock = () => { cluster_uuid: 'cluster-uuid', cluster_name: 'cluster-name', cluster_version: '8.0.0', + cluster_build_flavor: 'default', }), status$: new BehaviorSubject>({ level: ServiceStatusLevels.available, @@ -117,6 +123,15 @@ const createMock = () => { return mocked; }; +const createCapabilities = ( + parts: Partial = {} +): ElasticsearchCapabilities => { + return { + serverless: false, + ...parts, + }; +}; + export const elasticsearchServiceMock = { create: createMock, createInternalPreboot: createInternalPrebootContractMock, @@ -125,6 +140,7 @@ export const elasticsearchServiceMock = { createSetup: createSetupContractMock, createInternalStart: createInternalStartContractMock, createStart: createStartContractMock, + createCapabilities, ...elasticsearchClientMock, }; diff --git a/packages/core/elasticsearch/core-elasticsearch-server/index.ts b/packages/core/elasticsearch/core-elasticsearch-server/index.ts index da71ac13c8ac0..86d679ec689bc 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server/index.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server/index.ts @@ -30,6 +30,7 @@ export type { ElasticsearchServicePreboot, ElasticsearchServiceStart, ElasticsearchServiceSetup, + ElasticsearchCapabilities, } from './src/contracts'; export type { IElasticsearchConfig, ElasticsearchSslConfig } from './src/elasticsearch_config'; export type { ElasticsearchRequestHandlerContext } from './src/request_handler_context'; diff --git a/packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts b/packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts index 39fed7cbd2803..fced65ce95c79 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server/src/contracts.ts @@ -126,6 +126,24 @@ export interface ElasticsearchServiceStart { type: string, clientConfig?: Partial ) => ICustomClusterClient; + + /** + * Returns the capabilities for the default cluster. + */ + getCapabilities: () => ElasticsearchCapabilities; +} + +/** + * Represent the capabilities supported by a given ES cluster. + * + * @public + */ +export interface ElasticsearchCapabilities { + /** + * Indicates whether we're connected to a serverless version of elasticsearch. + * Required because some options aren't working for serverless and code needs to have the info to react accordingly. + */ + serverless: boolean; } /** diff --git a/packages/core/environment/core-environment-server-internal/src/resolve_uuid.test.ts b/packages/core/environment/core-environment-server-internal/src/resolve_uuid.test.ts index 353afe32921ce..32f149525463f 100644 --- a/packages/core/environment/core-environment-server-internal/src/resolve_uuid.test.ts +++ b/packages/core/environment/core-environment-server-internal/src/resolve_uuid.test.ts @@ -158,6 +158,15 @@ describe('resolveInstanceUuid', () => { }); }); + describe('when file exists but is empty', () => { + it('throws an explicit error for uuid formatting', async () => { + mockReadFile({ uuid: '' }); + await expect( + resolveInstanceUuid({ pathConfig, serverConfig, logger }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"data-folder/uuid contains an invalid UUID"`); + }); + }); + describe('when file contains a trailing new line', () => { it('returns the trimmed file uuid', async () => { mockReadFile({ uuid: DEFAULT_FILE_UUID + '\n' }); diff --git a/packages/core/environment/core-environment-server-internal/src/resolve_uuid.ts b/packages/core/environment/core-environment-server-internal/src/resolve_uuid.ts index 3ba6285fe6836..adac8547251a3 100644 --- a/packages/core/environment/core-environment-server-internal/src/resolve_uuid.ts +++ b/packages/core/environment/core-environment-server-internal/src/resolve_uuid.ts @@ -65,13 +65,16 @@ export async function resolveInstanceUuid({ async function readUuidFromFile(filepath: string, logger: Logger): Promise { const content = await readFileContent(filepath); + if (content === undefined) { + return undefined; + } if (content === UUID_7_6_0_BUG) { logger.debug(`UUID from 7.6.0 bug detected, ignoring file UUID`); return undefined; } - if (content && !content.match(uuidRegexp)) { + if (!content.match(uuidRegexp)) { throw new Error(`${filepath} contains an invalid UUID`); } 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 78cab6c6ea076..f12367419341f 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 @@ -399,8 +399,10 @@ export class HttpServer { const log = this.logger.get('http', 'server', 'response'); this.handleServerResponseEvent = (request) => { - const { message, meta } = getEcsResponseLog(request, this.log); - log.debug(message!, meta); + if (log.isLevelEnabled('debug')) { + const { message, meta } = getEcsResponseLog(request, this.log); + log.debug(message!, meta); + } }; this.server.events.on('response', this.handleServerResponseEvent); diff --git a/packages/core/logging/core-logging-common-internal/src/layouts/conversions/message.test.ts b/packages/core/logging/core-logging-common-internal/src/layouts/conversions/message.test.ts new file mode 100644 index 0000000000000..a08f4742bb978 --- /dev/null +++ b/packages/core/logging/core-logging-common-internal/src/layouts/conversions/message.test.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 { LogLevel, LogRecord } from '@kbn/logging'; +import { MessageConversion } from './message'; + +const baseRecord: LogRecord = { + pid: 1, + timestamp: new Date(), + level: LogLevel.Info, + context: '', + message: '', +}; + +describe('MessageConversion', () => { + test('it should keep break lines', () => { + expect( + MessageConversion.convert({ ...baseRecord, message: 'Hi!\nHow are you?' }, false) + ).toEqual('Hi!\nHow are you?'); + }); + + test('it should remove ANSI chars lines from the message', () => { + expect( + MessageConversion.convert( + { ...baseRecord, message: 'Blinking...\u001b[5;7;6mThis is Fine\u001b[27m' }, + false + ) + ).toEqual('Blinking...This is Fine'); + }); + + test('it should remove any unicode injection from the message', () => { + expect( + MessageConversion.convert( + { + ...baseRecord, + message: + '\u001b[31mESC-INJECTION-LFUNICODE:\u001b[32mSUCCESSFUL\u001b[0m\u0007\n\nInjecting 10.000 lols 😂\u001b[10000;b\u0007', + }, + false + ) + ).toEqual('ESC-INJECTION-LFUNICODE:SUCCESSFUL\n\nInjecting 10.000 lols 😂'); + }); +}); diff --git a/packages/core/logging/core-logging-common-internal/src/layouts/conversions/message.ts b/packages/core/logging/core-logging-common-internal/src/layouts/conversions/message.ts index 97fc4c60101ce..8bc9cd6c4115a 100644 --- a/packages/core/logging/core-logging-common-internal/src/layouts/conversions/message.ts +++ b/packages/core/logging/core-logging-common-internal/src/layouts/conversions/message.ts @@ -6,13 +6,20 @@ * Side Public License, v 1. */ +import ansiRegex from 'ansi-regex'; import { LogRecord } from '@kbn/logging'; import { Conversion } from './types'; +// Defining it globally because it's more performant than creating for each log entry +// We can reuse the same global RegExp here because `.replace()` automatically resets the `.lastIndex` of the RegExp. +const ANSI_ESCAPE_CODES_REGEXP = ansiRegex(); + export const MessageConversion: Conversion = { pattern: /%message/g, convert(record: LogRecord) { // Error stack is much more useful than just the message. - return (record.error && record.error.stack) || record.message; + const str = record.error?.stack || record.message; + // We need to validate it's a string because, despite types, there are use case where it's not a string :/ + return typeof str === 'string' ? str.replace(ANSI_ESCAPE_CODES_REGEXP, '') : str; }, }; diff --git a/packages/core/plugins/core-plugins-browser-mocks/src/plugins_service.mock.ts b/packages/core/plugins/core-plugins-browser-mocks/src/plugins_service.mock.ts index 56ea09aed483c..8342476961267 100644 --- a/packages/core/plugins/core-plugins-browser-mocks/src/plugins_service.mock.ts +++ b/packages/core/plugins/core-plugins-browser-mocks/src/plugins_service.mock.ts @@ -10,6 +10,7 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import { loggerMock } from '@kbn/logging-mocks'; import type { PluginInitializerContext } from '@kbn/core-plugins-browser'; import type { PluginsService, PluginsServiceSetup } from '@kbn/core-plugins-browser-internal'; +import type { BuildFlavor } from '@kbn/config/src/types'; const createSetupContractMock = () => { const setupContract: jest.Mocked = { @@ -27,7 +28,10 @@ const createStartContractMock = () => { return startContract as PluginsServiceSetup; }; -const createPluginInitializerContextMock = (config: unknown = {}) => { +const createPluginInitializerContextMock = ( + config: unknown = {}, + { buildFlavor = 'serverless' }: { buildFlavor?: BuildFlavor } = {} +) => { const mock: PluginInitializerContext = { opaqueId: Symbol(), env: { @@ -43,7 +47,7 @@ const createPluginInitializerContextMock = (config: unknown = {}) => { buildSha: 'buildSha', dist: false, buildDate: new Date('2023-05-15T23:12:09.000Z'), - buildFlavor: 'serverless', + buildFlavor, }, }, logger: loggerMock.create(), diff --git a/packages/core/plugins/core-plugins-browser-mocks/tsconfig.json b/packages/core/plugins/core-plugins-browser-mocks/tsconfig.json index 6b14fa13dd8b5..6413be0063abe 100644 --- a/packages/core/plugins/core-plugins-browser-mocks/tsconfig.json +++ b/packages/core/plugins/core-plugins-browser-mocks/tsconfig.json @@ -16,6 +16,7 @@ "@kbn/logging-mocks", "@kbn/core-plugins-browser-internal", "@kbn/core-plugins-browser", + "@kbn/config", ], "exclude": [ "target/**/*", 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 abd607141b4a4..5ca77254e5b50 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 @@ -246,7 +246,6 @@ export function createPluginSetupContext( setSpacesExtension: deps.savedObjects.setSpacesExtension, registerType: deps.savedObjects.registerType, getDefaultIndex: deps.savedObjects.getDefaultIndex, - getAllIndices: deps.savedObjects.getAllIndices, }, status: { core$: deps.status.core$, @@ -302,6 +301,7 @@ export function createPluginStartContext( elasticsearch: { client: deps.elasticsearch.client, createClient: deps.elasticsearch.createClient, + getCapabilities: deps.elasticsearch.getCapabilities, }, executionContext: deps.executionContext, http: { 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 280fa38c04344..d6738b4f42394 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 @@ -278,6 +278,14 @@ export class PluginsService implements CoreService value === true) + .map(([key]) => key); + if (configKeys.length > 0) { + this.coreContext.configService.addDynamicConfigPaths(plugin.configPath, configKeys); + } + } this.coreContext.configService.setSchema(plugin.configPath, configDescriptor.schema); } } 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 f949d039eb0ce..701792f24bc35 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 @@ -202,6 +202,7 @@ test('correctly orders plugins and returns exposed values for "setup" and "start setup: Record; start: Record; } + const plugins = new Map([ [ createPlugin('order-4', { required: ['order-2'] }), @@ -754,6 +755,70 @@ describe('stop', () => { jest.useRealTimers(); }); + const nextTick = () => new Promise((resolve) => setImmediate(resolve)); + + it('stops all plugins', async () => { + const [plugin1, plugin2, plugin3] = [ + createPlugin('plugin-1'), + createPlugin('plugin-2'), + createPlugin('plugin-3'), + ].map((plugin, index) => { + jest.spyOn(plugin, 'setup').mockResolvedValue(`setup-as-${index}`); + jest.spyOn(plugin, 'start').mockResolvedValue(`started-as-${index}`); + pluginsSystem.addPlugin(plugin); + return plugin; + }); + + const stopSpy1 = jest.spyOn(plugin1, 'stop').mockImplementationOnce(() => Promise.resolve()); + const stopSpy2 = jest.spyOn(plugin2, 'stop').mockImplementationOnce(() => Promise.resolve()); + const stopSpy3 = jest.spyOn(plugin3, 'stop').mockImplementationOnce(() => Promise.resolve()); + + mockCreatePluginSetupContext.mockImplementation(() => ({})); + + await pluginsSystem.setupPlugins(setupDeps); + const stopPromise = pluginsSystem.stopPlugins(); + + await nextTick(); + jest.runAllTimers(); + + await stopPromise; + + expect(stopSpy1).toHaveBeenCalledTimes(1); + expect(stopSpy2).toHaveBeenCalledTimes(1); + expect(stopSpy3).toHaveBeenCalledTimes(1); + }); + + it('stops plugins in the correct order', async () => { + // stop order: 3 => 1 => 2 + const [plugin1, plugin2, plugin3] = [ + createPlugin('plugin-1', { required: ['plugin-2'] }), + createPlugin('plugin-2'), + createPlugin('plugin-3', { required: ['plugin-1', 'plugin-2'] }), + ].map((plugin, index) => { + jest.spyOn(plugin, 'setup').mockResolvedValue(`setup-as-${index}`); + jest.spyOn(plugin, 'start').mockResolvedValue(`started-as-${index}`); + pluginsSystem.addPlugin(plugin); + return plugin; + }); + + const stopSpy1 = jest.spyOn(plugin1, 'stop').mockImplementationOnce(() => Promise.resolve()); + const stopSpy2 = jest.spyOn(plugin2, 'stop').mockImplementationOnce(() => Promise.resolve()); + const stopSpy3 = jest.spyOn(plugin3, 'stop').mockImplementationOnce(() => Promise.resolve()); + + mockCreatePluginSetupContext.mockImplementation(() => ({})); + + await pluginsSystem.setupPlugins(setupDeps); + const stopPromise = pluginsSystem.stopPlugins(); + + await nextTick(); + jest.runAllTimers(); + + await stopPromise; + + expect(stopSpy3.mock.invocationCallOrder[0]).toBeLessThan(stopSpy1.mock.invocationCallOrder[0]); + expect(stopSpy1.mock.invocationCallOrder[0]).toBeLessThan(stopSpy2.mock.invocationCallOrder[0]); + }); + it('waits for 30 sec to finish "stop" and move on to the next plugin.', async () => { const [plugin1, plugin2] = [createPlugin('timeout-stop-1'), createPlugin('timeout-stop-2')].map( (plugin, index) => { @@ -774,8 +839,11 @@ describe('stop', () => { await pluginsSystem.setupPlugins(setupDeps); const stopPromise = pluginsSystem.stopPlugins(); + await nextTick(); jest.runAllTimers(); + await stopPromise; + expect(stopSpy1).toHaveBeenCalledTimes(1); expect(stopSpy2).toHaveBeenCalledTimes(1); @@ -785,4 +853,42 @@ describe('stop', () => { ]) ); }); + + it('logs a message if a plugin fails top stop', async () => { + // stop order: 3 => 1 => 2 + const [plugin1, plugin2, plugin3] = [ + createPlugin('plugin-1', { required: ['plugin-2'] }), + createPlugin('plugin-2'), + createPlugin('plugin-3', { required: ['plugin-1', 'plugin-2'] }), + ].map((plugin, index) => { + jest.spyOn(plugin, 'setup').mockResolvedValue(`setup-as-${index}`); + jest.spyOn(plugin, 'start').mockResolvedValue(`started-as-${index}`); + pluginsSystem.addPlugin(plugin); + return plugin; + }); + + const stopSpy1 = jest + .spyOn(plugin1, 'stop') + .mockImplementationOnce(() => Promise.reject('woups')); + const stopSpy2 = jest.spyOn(plugin2, 'stop').mockImplementationOnce(() => Promise.resolve()); + const stopSpy3 = jest.spyOn(plugin3, 'stop').mockImplementationOnce(() => Promise.resolve()); + + mockCreatePluginSetupContext.mockImplementation(() => ({})); + + await pluginsSystem.setupPlugins(setupDeps); + const stopPromise = pluginsSystem.stopPlugins(); + + await nextTick(); + jest.runAllTimers(); + + await stopPromise; + + expect(stopSpy1).toHaveBeenCalledTimes(1); + expect(stopSpy2).toHaveBeenCalledTimes(1); + expect(stopSpy3).toHaveBeenCalledTimes(1); + + expect(loggingSystemMock.collect(logger).warn.flat()).toEqual( + expect.arrayContaining([`"plugin-1" thrown during stop: woups`]) + ); + }); }); 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 d7c4df71dd4fc..35e77e84381fd 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 @@ -224,21 +224,38 @@ export class PluginsSystem { this.log.info(`Stopping all plugins.`); - // Stop plugins in the reverse order of when they were set up. - while (this.satupPlugins.length > 0) { - const pluginName = this.satupPlugins.pop()!; - - this.log.debug(`Stopping plugin "${pluginName}"...`); + const reverseDependencyMap = buildReverseDependencyMap(this.plugins); + const pluginStopPromiseMap = new Map>(); + for (let i = this.satupPlugins.length - 1; i > -1; i--) { + const pluginName = this.satupPlugins[i]; + const plugin = this.plugins.get(pluginName)!; + const pluginDependant = reverseDependencyMap.get(pluginName)!; + const dependantPromises = pluginDependant.map( + (dependantName) => pluginStopPromiseMap.get(dependantName)! + ); - const resultMaybe = await withTimeout({ - promise: this.plugins.get(pluginName)!.stop(), - timeoutMs: 30 * Sec, + // Stop plugin as soon as all the dependant plugins are stopped. + const pluginStopPromise = Promise.all(dependantPromises).then(async () => { + this.log.debug(`Stopping plugin "${pluginName}"...`); + + try { + const resultMaybe = await withTimeout({ + promise: plugin.stop(), + timeoutMs: 30 * Sec, + }); + if (resultMaybe?.timedout) { + this.log.warn(`"${pluginName}" plugin didn't stop in 30sec., move on to the next.`); + } + } catch (e) { + this.log.warn(`"${pluginName}" thrown during stop: ${e}`); + } }); - - if (resultMaybe?.timedout) { - this.log.warn(`"${pluginName}" plugin didn't stop in 30sec., move on to the next.`); - } + pluginStopPromiseMap.set(pluginName, pluginStopPromise); } + + await Promise.allSettled(pluginStopPromiseMap.values()); + + this.log.info(`All plugins stopped.`); } /** @@ -334,3 +351,23 @@ export class PluginsSystem { return sortedPluginNames; } } + +const buildReverseDependencyMap = ( + pluginMap: Map +): Map => { + const reverseMap = new Map(); + for (const pluginName of pluginMap.keys()) { + reverseMap.set(pluginName, []); + } + for (const [pluginName, pluginWrapper] of pluginMap.entries()) { + const allDependencies = [...pluginWrapper.requiredPlugins, ...pluginWrapper.optionalPlugins]; + for (const dependency of allDependencies) { + // necessary to evict non-present optional dependency + if (pluginMap.has(dependency)) { + reverseMap.get(dependency)!.push(pluginName); + } + } + reverseMap.set(pluginName, []); + } + return reverseMap; +}; diff --git a/packages/core/plugins/core-plugins-server/index.ts b/packages/core/plugins/core-plugins-server/index.ts index 47aa0d04ac87c..0c80b60c3d111 100644 --- a/packages/core/plugins/core-plugins-server/index.ts +++ b/packages/core/plugins/core-plugins-server/index.ts @@ -18,6 +18,7 @@ export type { SharedGlobalConfig, MakeUsageFromSchema, ExposedToBrowserDescriptor, + DynamicConfigDescriptor, } from './src'; export { SharedGlobalConfigKeys } from './src'; diff --git a/packages/core/plugins/core-plugins-server/src/index.ts b/packages/core/plugins/core-plugins-server/src/index.ts index 94ad27dedbf12..322a8b5a13c09 100644 --- a/packages/core/plugins/core-plugins-server/src/index.ts +++ b/packages/core/plugins/core-plugins-server/src/index.ts @@ -18,6 +18,7 @@ export type { SharedGlobalConfig, MakeUsageFromSchema, ExposedToBrowserDescriptor, + DynamicConfigDescriptor, } from './types'; export { SharedGlobalConfigKeys } from './shared_global_config'; diff --git a/packages/core/plugins/core-plugins-server/src/types.ts b/packages/core/plugins/core-plugins-server/src/types.ts index 46773971d35ef..207df71df3279 100644 --- a/packages/core/plugins/core-plugins-server/src/types.ts +++ b/packages/core/plugins/core-plugins-server/src/types.ts @@ -34,7 +34,7 @@ export type PluginConfigSchema = Type; /** * Type defining the list of configuration properties that will be exposed on the client-side - * Object properties can either be fully exposed + * Object properties can either be fully exposed or narrowed down to specific keys. * * @public */ @@ -49,6 +49,23 @@ export type ExposedToBrowserDescriptor = { boolean; }; +/** + * Type defining the list of configuration properties that can be dynamically updated + * Object properties can either be fully exposed or narrowed down to specific keys. + * + * @public + */ +export type DynamicConfigDescriptor = { + [Key in keyof T]?: T[Key] extends Maybe + ? // handles arrays as primitive values + boolean + : T[Key] extends Maybe + ? // can be nested for objects + DynamicConfigDescriptor | boolean + : // primitives + boolean; +}; + /** * Describes a plugin configuration properties. * @@ -88,6 +105,10 @@ export interface PluginConfigDescriptor { * List of configuration properties that will be available on the client-side plugin. */ exposeToBrowser?: ExposedToBrowserDescriptor; + /** + * List of configuration properties that can be dynamically changed via the PUT /_settings API. + */ + dynamicConfig?: DynamicConfigDescriptor; /** * Schema to use to validate the plugin configuration. * 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 3428f9842d44f..6316dc056563c 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 @@ -519,6 +519,7 @@ Object { "branch": Any, "buildNumber": Any, "clusterInfo": Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster-uuid", "cluster_version": "8.0.0", @@ -590,6 +591,7 @@ Object { "branch": Any, "buildNumber": Any, "clusterInfo": Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster-uuid", "cluster_version": "8.0.0", @@ -720,6 +722,7 @@ Object { "branch": Any, "buildNumber": Any, "clusterInfo": Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster-uuid", "cluster_version": "8.0.0", @@ -791,6 +794,7 @@ Object { "branch": Any, "buildNumber": Any, "clusterInfo": Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster-uuid", "cluster_version": "8.0.0", @@ -858,6 +862,7 @@ Object { "branch": Any, "buildNumber": Any, "clusterInfo": Object { + "cluster_build_flavor": "default", "cluster_name": "cluster-name", "cluster_uuid": "cluster-uuid", "cluster_version": "8.0.0", diff --git a/packages/core/root/core-root-server-internal/src/register_service_config.ts b/packages/core/root/core-root-server-internal/src/register_service_config.ts index f646f9e538ae8..ccb6a745b6754 100644 --- a/packages/core/root/core-root-server-internal/src/register_service_config.ts +++ b/packages/core/root/core-root-server-internal/src/register_service_config.ts @@ -16,6 +16,7 @@ import { pidConfig } from '@kbn/core-environment-server-internal'; import { executionContextConfig } from '@kbn/core-execution-context-server-internal'; import { config as httpConfig, cspConfig, externalUrlConfig } from '@kbn/core-http-server-internal'; import { config as elasticsearchConfig } from '@kbn/core-elasticsearch-server-internal'; +import { config as coreAppConfig } from '@kbn/core-apps-server-internal'; import { opsConfig } from '@kbn/core-metrics-server-internal'; import { savedObjectsConfig, @@ -37,6 +38,7 @@ export function registerServiceConfig(configService: ConfigService) { cspConfig, deprecationConfig, elasticsearchConfig, + coreAppConfig, elasticApmConfig, executionContextConfig, externalUrlConfig, diff --git a/packages/core/root/core-root-server-internal/src/server.ts b/packages/core/root/core-root-server-internal/src/server.ts index 906e4bfbe7bf8..8f8a7f185474a 100644 --- a/packages/core/root/core-root-server-internal/src/server.ts +++ b/packages/core/root/core-root-server-internal/src/server.ts @@ -350,7 +350,7 @@ export class Server { this.#pluginsInitialized = pluginsSetup.initialized; this.registerCoreContext(coreSetup); - this.coreApp.setup(coreSetup, uiPlugins); + await this.coreApp.setup(coreSetup, uiPlugins); setupTransaction?.end(); this.uptimePerStep.setup = { start: setupStartUptime, end: performance.now() }; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/index.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/index.ts index 9989b4264f28f..e7bd523c0e741 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/index.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/index.ts @@ -23,6 +23,10 @@ export { type IPreflightCheckHelper, type PreflightCheckNamespacesParams, type PreflightCheckNamespacesResult, + type PreflightDocParams, + type PreflightDocResult, + type PreflightNSParams, + type PreflightNSResult, } from './preflight_check'; export interface RepositoryHelpers { diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/preflight_check.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/preflight_check.ts index 5cf2bfbf21d99..1e39761d99d6e 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/preflight_check.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/helpers/preflight_check.ts @@ -117,7 +117,6 @@ export class PreflightCheckHelper { if (!this.registry.isMultiNamespace(type)) { throw new Error(`Cannot make preflight get request for non-multi-namespace type '${type}'.`); } - const { body, statusCode, headers } = await this.client.get( { id: this.serializer.generateRawId(undefined, type, id), @@ -151,8 +150,83 @@ export class PreflightCheckHelper { }; } + /** + * Pre-flight check fetching the document regardless of its namespace type for update. + */ + public async preflightGetDocForUpdate({ + type, + id, + namespace, + }: PreflightDocParams): Promise { + const { statusCode, body, headers } = await this.client.get( + { + id: this.serializer.generateRawId(namespace, type, id), + index: this.getIndexForType(type), + }, + { ignore: [404], meta: true } + ); + + // checking if the 404 is from Elasticsearch + if (isNotFoundFromUnsupportedServer({ statusCode, headers })) { + throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(type, id); + } + + const indexFound = statusCode !== 404; + if (indexFound && isFoundGetResponse(body)) { + return { + checkDocFound: 'found', + rawDocSource: body, + }; + } + + return { + checkDocFound: 'not_found', + }; + } + + /** + * Pre-flight check to ensure that a multi-namespace object exists in the current namespace for update API. + */ + public preflightCheckNamespacesForUpdate({ + type, + namespace, + initialNamespaces, + preflightDocResult, + }: PreflightNSParams): PreflightNSResult { + const { checkDocFound, rawDocSource } = preflightDocResult; + if (!this.registry.isMultiNamespace(type)) { + return { + checkSkipped: true, + }; + } + + const namespaces = initialNamespaces ?? [SavedObjectsUtils.namespaceIdToString(namespace)]; + + if (checkDocFound === 'found' && rawDocSource !== undefined) { + if (!rawDocExistsInNamespaces(this.registry, rawDocSource, namespaces)) { + return { checkResult: 'found_outside_namespace', checkSkipped: false }; + } + return { + checkResult: 'found_in_namespace', + savedObjectNamespaces: + initialNamespaces ?? getSavedObjectNamespaces(namespace, rawDocSource), + rawDocSource, + checkSkipped: false, + }; + } + + return { + checkResult: 'not_found', + savedObjectNamespaces: initialNamespaces ?? getSavedObjectNamespaces(namespace), + checkSkipped: false, + }; + } + /** * Pre-flight check to ensure that an upsert which would create a new object does not result in an alias conflict. + * + * If an upsert would result in the creation of a new object, we need to check for alias conflicts too. + * This takes an extra round trip to Elasticsearch, but this won't happen often. */ public async preflightCheckForUpsertAliasConflict( type: string, @@ -189,6 +263,39 @@ export interface PreflightCheckNamespacesParams { initialNamespaces?: string[]; } +/** + * @internal + */ +export interface PreflightNSParams { + /** The object type to fetch */ + type: string; + /** The object ID to fetch */ + id: string; + /** The current space */ + namespace: string | undefined; + /** Optional; for an object that is being created, this specifies the initial namespace(s) it will exist in (overriding the current space) */ + initialNamespaces?: string[]; + /** Optional; for a pre-fetched object */ + preflightDocResult: PreflightDocResult; +} + +/** + * @internal + */ +export interface PreflightNSResult { + /** If the object exists, and whether or not it exists in the current space */ + checkResult?: 'not_found' | 'found_in_namespace' | 'found_outside_namespace'; + /** + * What namespace(s) the object should exist in, if it needs to be created; practically speaking, this will never be undefined if + * checkResult == not_found or checkResult == found_in_namespace + */ + savedObjectNamespaces?: string[]; + /** The source of the raw document, if the object already exists */ + rawDocSource?: GetResponseFound; + /** Indicates if the namespaces check is called or not. Non-multinamespace types are not shareable */ + checkSkipped?: boolean; +} + /** * @internal */ @@ -203,3 +310,30 @@ export interface PreflightCheckNamespacesResult { /** The source of the raw document, if the object already exists */ rawDocSource?: GetResponseFound; } + +/** + * @internal + */ +export interface PreflightDocParams { + /** The object type to fetch */ + type: string; + /** The object ID to fetch */ + id: string; + /** The current space */ + namespace: string | undefined; + /** + * optional migration version compatibility. + * {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} + */ + migrationVersionCompatibility?: 'compatible' | 'raw'; +} + +/** + * @internal + */ +export interface PreflightDocResult { + /** If the object exists, and whether or not it exists in the current space */ + checkDocFound: 'not_found' | 'found'; + /** The source of the raw document, if the object already exists in the server's version (unsafe to use) */ + rawDocSource?: GetResponseFound; +} diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.test.ts new file mode 100644 index 0000000000000..dd5c51c6b433d --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.test.ts @@ -0,0 +1,741 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* eslint-disable @typescript-eslint/no-shadow */ + +import { mockGetCurrentTime, mockPreflightCheckForCreate } from '../repository.test.mock'; + +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { + type SavedObjectUnsanitizedDoc, + type SavedObjectReference, + SavedObjectsRawDocSource, + SavedObjectsErrorHelpers, +} from '@kbn/core-saved-objects-server'; +import { ALL_NAMESPACES_STRING } from '@kbn/core-saved-objects-utils-server'; +import { SavedObjectsRepository } from '../repository'; +import { loggerMock } from '@kbn/logging-mocks'; +import { + SavedObjectsSerializer, + encodeHitVersion, +} from '@kbn/core-saved-objects-base-server-internal'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { kibanaMigratorMock } from '../../mocks'; +import { + NAMESPACE_AGNOSTIC_TYPE, + MULTI_NAMESPACE_ISOLATED_TYPE, + HIDDEN_TYPE, + mockVersionProps, + mockTimestampFields, + mockTimestamp, + mappings, + mockVersion, + createRegistry, + createDocumentMigrator, + getMockGetResponse, + createSpySerializer, + createBadRequestErrorPayload, + createConflictErrorPayload, + createGenericNotFoundErrorPayload, + updateSuccess, +} from '../../test_helpers/repository.test.common'; + +describe('SavedObjectsRepository', () => { + let client: ReturnType; + let repository: SavedObjectsRepository; + let migrator: ReturnType; + let logger: ReturnType; + let serializer: jest.Mocked; + + const registry = createRegistry(); + const documentMigrator = createDocumentMigrator(registry); + + const expectMigrationArgs = (args: unknown, contains = true, n = 1) => { + const obj = contains ? expect.objectContaining(args) : expect.not.objectContaining(args); + expect(migrator.migrateDocument).toHaveBeenNthCalledWith( + n, + obj, + expect.objectContaining({ + allowDowngrade: expect.any(Boolean), + }) + ); + }; + + beforeEach(() => { + client = elasticsearchClientMock.createElasticsearchClient(); + migrator = kibanaMigratorMock.create(); + documentMigrator.prepareMigrations(); + migrator.migrateDocument = jest.fn().mockImplementation(documentMigrator.migrate); + migrator.runMigrations = jest.fn().mockResolvedValue([{ status: 'skipped' }]); + logger = loggerMock.create(); + + // create a mock serializer "shim" so we can track function calls, but use the real serializer's implementation + serializer = createSpySerializer(registry); + + const allTypes = registry.getAllTypes().map((type) => type.name); + const allowedTypes = [...new Set(allTypes.filter((type) => !registry.isHidden(type)))]; + + // @ts-expect-error must use the private constructor to use the mocked serializer + repository = new SavedObjectsRepository({ + index: '.kibana-test', + mappings, + client, + migrator, + typeRegistry: registry, + serializer, + allowedTypes, + logger, + }); + + mockGetCurrentTime.mockReturnValue(mockTimestamp); + }); + + describe('#update', () => { + const id = 'logstash-*'; + const type = 'index-pattern'; + const attributes = { title: 'Testing' }; + const namespace = 'foo-namespace'; + const references = [ + { + name: 'ref_0', + type: 'test', + id: '1', + }, + ]; + const originId = 'some-origin-id'; + const mockMigrationVersion = { foo: '2.3.4' }; + const mockMigrateDocumentForUpdate = (doc: SavedObjectUnsanitizedDoc) => { + const response = { + ...doc, + attributes: { + ...doc.attributes, + ...(doc.attributes?.title && { title: `${doc.attributes.title}!!` }), + }, + migrationVersion: mockMigrationVersion, + managed: doc.managed ?? false, + references: doc.references || [ + { + name: 'ref_0', + type: 'test', + id: '1', + }, + ], + }; + return response; + }; + + beforeEach(() => { + mockPreflightCheckForCreate.mockReset(); + mockPreflightCheckForCreate.mockImplementation(({ objects }) => { + return Promise.resolve(objects.map(({ type, id }) => ({ type, id }))); // respond with no errors by default + }); + client.create.mockResponseImplementation((params) => { + return { + body: { + _id: params.id, + ...mockVersionProps, + } as estypes.CreateResponse, + }; + }); + }); + + describe('client calls', () => { + it(`should use the ES get action then index action when type is not multi-namespace for existing objects`, async () => { + const type = 'index-pattern'; + const id = 'logstash-*'; + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess(client, repository, registry, type, id, attributes, { namespace }); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); + expect(client.index).toHaveBeenCalledTimes(1); + }); + + it(`should use the ES get action then index action when type is multi-namespace for existing objects`, async () => { + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess( + client, + repository, + registry, + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes + ); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); + expect(client.index).toHaveBeenCalledTimes(1); + }); + + it(`should use the ES get action then index action when type is namespace agnostic for existing objects`, async () => { + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess(client, repository, registry, NAMESPACE_AGNOSTIC_TYPE, id, attributes); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); + expect(client.index).toHaveBeenCalledTimes(1); + }); + + it(`should check for alias conflicts if a new multi-namespace object before create action would be created then create action to create the object`, async () => { + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess( + client, + repository, + registry, + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes, + { upsert: true }, + { mockGetResponseAsNotFound: { found: false } as estypes.GetResponse } + ); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); + expect(client.create).toHaveBeenCalledTimes(1); + }); + + it(`defaults to empty array with no input references`, async () => { + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess(client, repository, registry, type, id, attributes); + expect( + (client.index.mock.calls[0][0] as estypes.CreateRequest).body! + .references + ).toEqual([]); // we're indexing a full new doc, serializer adds default if not defined + }); + + it(`accepts custom references array 1`, async () => { + const test = async (references: SavedObjectReference[]) => { + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess(client, repository, registry, type, id, attributes, { + references, + }); + expect( + (client.index.mock.calls[0][0] as estypes.CreateRequest).body! + .references + ).toEqual(references); + client.index.mockClear(); + }; + await test(references); + }); + it(`accepts custom references array 2`, async () => { + const test = async (references: SavedObjectReference[]) => { + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess(client, repository, registry, type, id, attributes, { + references, + }); + expect( + (client.index.mock.calls[0][0] as estypes.CreateRequest).body! + .references + ).toEqual(references); + client.index.mockClear(); + }; + await test([{ type: 'foo', id: '42', name: 'some ref' }]); + }); + it(`accepts custom references array 3`, async () => { + const test = async (references: SavedObjectReference[]) => { + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess(client, repository, registry, type, id, attributes, { + references, + }); + expect( + (client.index.mock.calls[0][0] as estypes.CreateRequest).body! + .references + ).toEqual(references); + client.index.mockClear(); + }; + await test([]); + }); + + it(`uses the 'upsertAttributes' option when specified for a single-namespace type that does not exist`, async () => { + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess( + client, + repository, + registry, + type, + id, + attributes, + { + upsert: { + title: 'foo', + description: 'bar', + }, + }, + { mockGetResponseAsNotFound: { found: false } as estypes.GetResponse } + ); + + const expected = { + 'index-pattern': { description: 'bar', title: 'foo' }, + type: 'index-pattern', + ...mockTimestampFields, + }; + expect( + (client.create.mock.calls[0][0] as estypes.CreateRequest).body! + ).toEqual(expected); + }); + + it(`uses the 'upsertAttributes' option when specified for a multi-namespace type that does not exist`, async () => { + const options = { upsert: { title: 'foo', description: 'bar' } }; + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess( + client, + repository, + registry, + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes, + { + upsert: { + title: 'foo', + description: 'bar', + }, + }, + { + mockGetResponseAsNotFound: { found: false } as estypes.GetResponse, + } + ); + await repository.update(MULTI_NAMESPACE_ISOLATED_TYPE, id, attributes, options); + expect(client.get).toHaveBeenCalledTimes(2); + const expectedType = { + multiNamespaceIsolatedType: { description: 'bar', title: 'foo' }, + namespaces: ['default'], + type: 'multiNamespaceIsolatedType', + ...mockTimestampFields, + }; + expect( + (client.create.mock.calls[0][0] as estypes.CreateRequest).body! + ).toEqual(expectedType); + }); + + it(`ignores the 'upsertAttributes' option when specified for a multi-namespace type that already exists`, async () => { + // attributes don't change + const options = { upsert: { title: 'foo', description: 'bar' } }; + migrator.migrateDocument.mockImplementation((doc) => ({ ...doc, migrated: true })); + await updateSuccess( + client, + repository, + registry, + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes, + options + ); + await repository.update(MULTI_NAMESPACE_ISOLATED_TYPE, id, attributes, options); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining({ + id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${id}`, + index: '.kibana-test_8.0.0-testing', + refresh: 'wait_for', + require_alias: true, + body: expect.objectContaining({ + multiNamespaceIsolatedType: { title: 'Testing' }, + namespaces: ['default'], + references: [], + type: 'multiNamespaceIsolatedType', + ...mockTimestampFields, + }), + }), + expect.anything() + ); + }); + + it(`doesn't accept custom references if not an array`, async () => { + const test = async (references: unknown) => { + migrator.migrateDocument.mockImplementation(mockMigrateDocumentForUpdate); + await updateSuccess(client, repository, registry, type, id, attributes, { + // @ts-expect-error references is unknown + references, + }); + expect( + (client.index.mock.calls[0][0] as estypes.CreateRequest).body! + .references + ).toEqual([]); + client.index.mockClear(); + client.create.mockClear(); + }; + await test('string'); + await test(123); + await test(true); + await test(null); + }); + + it(`defaults to a refresh setting of wait_for`, async () => { + migrator.migrateDocument.mockImplementation(mockMigrateDocumentForUpdate); + await updateSuccess(client, repository, registry, type, id, { foo: 'bar' }); + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining({ + refresh: 'wait_for', + }), + expect.anything() + ); + }); + + it(`defaults to the version of the existing document when type is multi-namespace`, async () => { + migrator.migrateDocument.mockImplementation(mockMigrateDocumentForUpdate); + await updateSuccess( + client, + repository, + registry, + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes, + { references } + ); + const versionProperties = { + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }; + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining(versionProperties), + expect.anything() + ); + }); + + it(`accepts version`, async () => { + migrator.migrateDocument.mockImplementation(mockMigrateDocumentForUpdate); + await updateSuccess(client, repository, registry, type, id, attributes, { + version: encodeHitVersion({ _seq_no: 100, _primary_term: 200 }), + }); + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining({ if_seq_no: 100, if_primary_term: 200 }), + expect.anything() + ); + }); + + it('retries the operation in case of conflict error', async () => { + client.get.mockResponse(getMockGetResponse(registry, { type, id })); + + client.index + .mockImplementationOnce(() => { + throw SavedObjectsErrorHelpers.createConflictError(type, id, 'conflict'); + }) + .mockImplementationOnce(() => { + throw SavedObjectsErrorHelpers.createConflictError(type, id, 'conflict'); + }) + .mockResponseImplementation((params) => { + return { + body: { + _id: params.id, + _seq_no: 1, + _primary_term: 1, + }, + } as any; + }); + + await repository.update(type, id, attributes, { retryOnConflict: 3 }); + + expect(client.get).toHaveBeenCalledTimes(3); + expect(client.index).toHaveBeenCalledTimes(3); + }); + + it('retries the operation a maximum of `retryOnConflict` times', async () => { + client.get.mockResponse(getMockGetResponse(registry, { type, id })); + + client.index.mockImplementation(() => { + throw SavedObjectsErrorHelpers.createConflictError(type, id, 'conflict'); + }); + + await expect( + repository.update(type, id, attributes, { retryOnConflict: 3 }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Saved object [index-pattern/logstash-*] conflict"` + ); + + expect(client.get).toHaveBeenCalledTimes(4); + expect(client.index).toHaveBeenCalledTimes(4); + }); + + it('default to a `retry_on_conflict` setting of `0` when `version` is provided', async () => { + client.get.mockResponse(getMockGetResponse(registry, { type, id })); + + client.index.mockImplementation(() => { + throw SavedObjectsErrorHelpers.createConflictError(type, id, 'conflict'); + }); + + await expect( + repository.update(type, id, attributes, { + version: encodeHitVersion({ _seq_no: 100, _primary_term: 200 }), + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Saved object [index-pattern/logstash-*] conflict"` + ); + + expect(client.get).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledTimes(1); + }); + + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + await updateSuccess(client, repository, registry, type, id, attributes, { namespace }); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining({ id: expect.stringMatching(`${namespace}:${type}:${id}`) }), // namespace expected: globalType + expect.anything() + ); + }); + + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + await updateSuccess(client, repository, registry, type, id, attributes, { references }); + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining({ id: expect.stringMatching(`${type}:${id}`) }), + expect.anything() + ); + }); + + it(`normalizes options.namespace from 'default' to undefined`, async () => { + await updateSuccess(client, repository, registry, type, id, attributes, { + references, + namespace: 'default', + }); + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining({ id: expect.stringMatching(`${type}:${id}`) }), + expect.anything() + ); + }); + + it(`doesn't prepend namespace to the id when using agnostic-namespace type`, async () => { + await updateSuccess(client, repository, registry, NAMESPACE_AGNOSTIC_TYPE, id, attributes, { + namespace, + }); + + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining({ + id: expect.stringMatching(`${NAMESPACE_AGNOSTIC_TYPE}:${id}`), + }), + expect.anything() + ); + }); + + it(`doesn't prepend namespace to the id when using multi-namespace type`, async () => { + await updateSuccess( + client, + repository, + registry, + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes, + { namespace } + ); + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining({ + id: expect.stringMatching(`${MULTI_NAMESPACE_ISOLATED_TYPE}:${id}`), + }), + expect.anything() + ); + }); + }); + + describe('errors', () => { + const expectNotFoundError = async (type: string, id: string) => { + await expect( + repository.update(type, id, {}, { migrationVersionCompatibility: 'raw' }) + ).rejects.toThrowError(createGenericNotFoundErrorPayload(type, id)); + }; + + it(`throws when options.namespace is '*'`, async () => { + await expect( + repository.update(type, id, attributes, { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestErrorPayload('"options.namespace" cannot be "*"')); + }); + + it(`throws when type is invalid`, async () => { + await expectNotFoundError('unknownType', id); + expect(client.index).not.toHaveBeenCalled(); + }); + + it(`throws when type is hidden`, async () => { + await expectNotFoundError(HIDDEN_TYPE, id); + expect(client.index).not.toHaveBeenCalled(); + }); + + it(`throws when id is empty`, async () => { + await expect(repository.update(type, '', attributes)).rejects.toThrowError( + createBadRequestErrorPayload('id cannot be empty') + ); + expect(client.index).not.toHaveBeenCalled(); + }); + + it(`throws when ES is unable to find the document during get`, async () => { + client.get.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise( + { found: false } as estypes.GetResponse, + undefined + ) + ); + await expectNotFoundError(MULTI_NAMESPACE_ISOLATED_TYPE, id); + expect(client.get).toHaveBeenCalledTimes(1); + }); + + it(`throws when ES is unable to find the index during get`, async () => { + client.get.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise({} as estypes.GetResponse, { + statusCode: 404, + }) + ); + await expectNotFoundError(MULTI_NAMESPACE_ISOLATED_TYPE, id); + expect(client.get).toHaveBeenCalledTimes(1); + }); + + it(`throws when type is multi-namespace and the document exists, but not in this namespace`, async () => { + const response = getMockGetResponse( + registry, + { type: MULTI_NAMESPACE_ISOLATED_TYPE, id }, + namespace + ); + client.get.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise(response) + ); + await expectNotFoundError(MULTI_NAMESPACE_ISOLATED_TYPE, id); + expect(client.get).toHaveBeenCalledTimes(1); + }); + + it(`throws when there is an alias conflict from preflightCheckForCreate`, async () => { + client.get.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise({ + found: false, + } as estypes.GetResponse) + ); + mockPreflightCheckForCreate.mockResolvedValue([ + { type: 'type', id: 'id', error: { type: 'aliasConflict' } }, + ]); + await expect( + repository.update( + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + { attr: 'value' }, + { + upsert: { + upsertAttr: 'val', + attr: 'value', + }, + } + ) + ).rejects.toThrowError(createConflictErrorPayload(MULTI_NAMESPACE_ISOLATED_TYPE, id)); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); + expect(client.index).not.toHaveBeenCalled(); + }); + + it(`does not throw when there is a different error from preflightCheckForCreate`, async () => { + mockPreflightCheckForCreate.mockResolvedValue([ + { type: 'type', id: 'id', error: { type: 'conflict' } }, + ]); + await updateSuccess( + client, + repository, + registry, + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes, + { upsert: true }, + { mockGetResponseAsNotFound: { found: false } as estypes.GetResponse } + ); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); + expect(client.create).toHaveBeenCalledTimes(1); + }); + + it(`does not throw when the document does not exist`, async () => { + expect(client.create).not.toHaveBeenCalled(); + await expectNotFoundError(type, id); + }); + }); + + describe('migration', () => { + it('migrates the fetched document from get', async () => { + const type = 'index-pattern'; + const id = 'logstash-*'; + migrator.migrateDocument.mockImplementationOnce((doc) => ({ ...doc, migrated: true })); + await updateSuccess(client, repository, registry, type, id, attributes); + expect(migrator.migrateDocument).toHaveBeenCalledTimes(2); + expectMigrationArgs({ + id, + type, + }); + }); + + it('migrates the input arguments when upsert is used', async () => { + const options = { + upsert: { + title: 'foo', + description: 'bar', + }, + }; + const internalOptions = { + mockGetResponseAsNotFound: { found: false } as estypes.GetResponse, + }; + await updateSuccess( + client, + repository, + registry, + type, + id, + attributes, + options, + internalOptions + ); + expect(migrator.migrateDocument).toHaveBeenCalledTimes(1); + expectMigrationArgs({ + id, + type, + }); + }); + }); + + describe('returns', () => { + it(`returns _seq_no and _primary_term encoded as version`, async () => { + const result = await updateSuccess(client, repository, registry, type, id, attributes, { + namespace, + references, + }); + expect(result).toEqual({ + id, + type, + ...mockTimestampFields, + version: mockVersion, + attributes, + references, + namespaces: [namespace], + }); + }); + + it(`includes namespaces if type is multi-namespace`, async () => { + const result = await updateSuccess( + client, + repository, + registry, + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes + ); + expect(result).toMatchObject({ + namespaces: expect.any(Array), + }); + }); + + it(`includes namespaces if type is not multi-namespace`, async () => { + const result = await updateSuccess(client, repository, registry, type, id, attributes); + expect(result).toMatchObject({ + namespaces: ['default'], + }); + }); + + it(`includes originId property if present in cluster call response`, async () => { + const result = await updateSuccess( + client, + repository, + registry, + type, + id, + attributes, + {}, + { originId } + ); + expect(result).toMatchObject({ originId }); + }); + }); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.ts index 27f3d45c642de..e119d6e6303db 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.ts @@ -10,19 +10,21 @@ import { SavedObjectsErrorHelpers, type SavedObject, type SavedObjectSanitizedDoc, - SavedObjectsRawDoc, - SavedObjectsRawDocSource, } from '@kbn/core-saved-objects-server'; import { SavedObjectsUtils } from '@kbn/core-saved-objects-utils-server'; -import { encodeHitVersion } from '@kbn/core-saved-objects-base-server-internal'; import { + decodeRequestVersion, + encodeHitVersion, +} from '@kbn/core-saved-objects-base-server-internal'; +import type { SavedObjectsUpdateOptions, SavedObjectsUpdateResponse, } from '@kbn/core-saved-objects-api-server'; +import { isNotFoundFromUnsupportedServer } from '@kbn/core-elasticsearch-server-internal'; import { DEFAULT_REFRESH_SETTING, DEFAULT_RETRY_COUNT } from '../constants'; -import { getCurrentTime, getExpectedVersionProperties } from './utils'; -import { ApiExecutionContext } from './types'; -import { PreflightCheckNamespacesResult } from './helpers'; +import { isValidRequest } from '../utils'; +import { getCurrentTime, getSavedObjectFromSource, mergeForUpdate } from './utils'; +import type { ApiExecutionContext } from './types'; export interface PerformUpdateParams { type: string; @@ -32,84 +34,141 @@ export interface PerformUpdateParams { } export const performUpdate = async ( + updateParams: PerformUpdateParams, + apiContext: ApiExecutionContext +): Promise> => { + const { type, id, options } = updateParams; + const { allowedTypes, helpers } = apiContext; + const namespace = helpers.common.getCurrentNamespace(options.namespace); + + // check request is valid + const { validRequest, error } = isValidRequest({ allowedTypes, type, id }); + if (!validRequest && error) { + throw error; + } + + const maxAttempts = options.version ? 1 : 1 + DEFAULT_RETRY_COUNT; + + // handle retryOnConflict manually by reattempting the operation in case of conflict errors + let response: SavedObjectsUpdateResponse; + for (let currentAttempt = 1; currentAttempt <= maxAttempts; currentAttempt++) { + try { + response = await executeUpdate(updateParams, apiContext, { namespace }); + break; + } catch (e) { + if ( + SavedObjectsErrorHelpers.isConflictError(e) && + e.retryableConflict && + currentAttempt < maxAttempts + ) { + continue; + } + throw e; + } + } + + return response!; +}; + +export const executeUpdate = async ( { id, type, attributes, options }: PerformUpdateParams, - { - registry, - helpers, - allowedTypes, - client, - serializer, - migrator, - extensions = {}, - }: ApiExecutionContext + { registry, helpers, client, serializer, extensions = {}, logger }: ApiExecutionContext, + { namespace }: { namespace: string | undefined } ): Promise> => { const { common: commonHelper, encryption: encryptionHelper, preflight: preflightHelper, migration: migrationHelper, + validation: validationHelper, } = helpers; const { securityExtension } = extensions; - const namespace = commonHelper.getCurrentNamespace(options.namespace); - if (!allowedTypes.includes(type)) { - throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); - } - if (!id) { - throw SavedObjectsErrorHelpers.createBadRequestError('id cannot be empty'); // prevent potentially upserting a saved object with an empty ID - } - const { version, references, upsert, refresh = DEFAULT_REFRESH_SETTING, - retryOnConflict = version ? 0 : DEFAULT_RETRY_COUNT, + migrationVersionCompatibility, } = options; - let preflightResult: PreflightCheckNamespacesResult | undefined; - if (registry.isMultiNamespace(type)) { - preflightResult = await preflightHelper.preflightCheckNamespaces({ - type, - id, - namespace, - }); - } + // Preflight calls to get the doc and check namespaces for multinamespace types. + const preflightDocResult = await preflightHelper.preflightGetDocForUpdate({ + type, + id, + namespace, + }); - const existingNamespaces = preflightResult?.savedObjectNamespaces ?? []; + const preflightDocNSResult = preflightHelper.preflightCheckNamespacesForUpdate({ + type, + id, + namespace, + preflightDocResult, + }); + const existingNamespaces = preflightDocNSResult?.savedObjectNamespaces ?? []; const authorizationResult = await securityExtension?.authorizeUpdate({ namespace, object: { type, id, existingNamespaces }, }); - if ( - preflightResult?.checkResult === 'found_outside_namespace' || - (!upsert && preflightResult?.checkResult === 'not_found') - ) { + // validate if an update (directly update or create the object instead) can be done, based on if the doc exists or not + const docOutsideNamespace = preflightDocNSResult?.checkResult === 'found_outside_namespace'; + const docNotFound = + preflightDocNSResult?.checkResult === 'not_found' || + preflightDocResult.checkDocFound === 'not_found'; + + // doc not in namespace, or doc not found but we're not upserting => throw 404 + if (docOutsideNamespace || (docNotFound && !upsert)) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } - if (upsert && preflightResult?.checkResult === 'not_found') { - // If an upsert would result in the creation of a new object, we need to check for alias conflicts too. - // This takes an extra round trip to Elasticsearch, but this won't happen often. - // TODO: improve performance by combining these into a single preflight check + + if (upsert && preflightDocNSResult?.checkResult === 'not_found') { + // we only need to check multi-namespace objects. Single and agnostic types do not have aliases. + // throws SavedObjectsErrorHelpers.createConflictError(type, id) if there is one await preflightHelper.preflightCheckForUpsertAliasConflict(type, id, namespace); } + + // migrate the existing doc to the current version + let migrated: SavedObject; + if (preflightDocResult.checkDocFound === 'found') { + const document = getSavedObjectFromSource( + registry, + type, + id, + preflightDocResult.rawDocSource!, + { migrationVersionCompatibility } + ); + try { + migrated = migrationHelper.migrateStorageDocument(document) as SavedObject; + } catch (migrateStorageDocError) { + throw SavedObjectsErrorHelpers.decorateGeneralError( + migrateStorageDocError, + 'Failed to migrate document to the latest version.' + ); + } + } + // END ALL PRE_CLIENT CALL CHECKS && MIGRATE EXISTING DOC; + const time = getCurrentTime(); + let updatedOrCreatedSavedObject: SavedObject; + // `upsert` option set and document was not found -> we need to perform an upsert operation + const shouldPerformUpsert = upsert && docNotFound; - let rawUpsert: SavedObjectsRawDoc | undefined; - // don't include upsert if the object already exists; ES doesn't allow upsert in combination with version properties - if (upsert && (!preflightResult || preflightResult.checkResult === 'not_found')) { - let savedObjectNamespace: string | undefined; - let savedObjectNamespaces: string[] | undefined; + let savedObjectNamespace: string | undefined; + let savedObjectNamespaces: string[] | undefined; - if (registry.isSingleNamespace(type) && namespace) { - savedObjectNamespace = namespace; - } else if (registry.isMultiNamespace(type)) { - savedObjectNamespaces = preflightResult!.savedObjectNamespaces; - } + if (namespace && registry.isSingleNamespace(type)) { + savedObjectNamespace = namespace; + } else if (registry.isMultiNamespace(type)) { + savedObjectNamespaces = preflightDocNSResult.savedObjectNamespaces; + } - const migrated = migrationHelper.migrateInputDocument({ + // UPSERT CASE START + if (shouldPerformUpsert) { + // ignore attributes if creating a new doc: only use the upsert attributes + // don't include upsert if the object already exists; ES doesn't allow upsert in combination with version properties + const migratedUpsert = migrationHelper.migrateInputDocument({ id, type, ...(savedObjectNamespace && { namespace: savedObjectNamespace }), @@ -118,31 +177,111 @@ export const performUpdate = async ( ...(await encryptionHelper.optionallyEncryptAttributes(type, id, namespace, upsert)), }, updated_at: time, + ...(Array.isArray(references) && { references }), + }) as SavedObjectSanitizedDoc; + validationHelper.validateObjectForCreate(type, migratedUpsert); + const rawUpsert = serializer.savedObjectToRaw(migratedUpsert); + + const createRequestParams = { + id: rawUpsert._id, + index: commonHelper.getIndexForType(type), + refresh, + body: rawUpsert._source, + ...(version ? decodeRequestVersion(version) : {}), + require_alias: true, + }; + + const { + body: createDocResponseBody, + statusCode, + headers, + } = await client.create(createRequestParams, { meta: true }).catch((err) => { + if (SavedObjectsErrorHelpers.isEsUnavailableError(err)) { + throw err; + } + if (SavedObjectsErrorHelpers.isNotFoundError(err)) { + // see "404s from missing index" above + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); + } + if (SavedObjectsErrorHelpers.isConflictError(err)) { + // flag the error as being caused by an update conflict + err.retryableConflict = true; + } + throw err; }); - rawUpsert = serializer.savedObjectToRaw(migrated as SavedObjectSanitizedDoc); - } + if (isNotFoundFromUnsupportedServer({ statusCode, headers })) { + throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(id, type); + } + // client.create doesn't return the index document. + // Use rawUpsert as the _source + const upsertedSavedObject = serializer.rawToSavedObject( + { + ...rawUpsert, + ...createDocResponseBody, + }, + { migrationVersionCompatibility } + ); + const { originId } = upsertedSavedObject ?? {}; + let namespaces: string[] = []; + if (!registry.isNamespaceAgnostic(type)) { + namespaces = upsertedSavedObject.namespaces ?? [ + SavedObjectsUtils.namespaceIdToString(upsertedSavedObject.namespace), + ]; + } - const doc = { - [type]: await encryptionHelper.optionallyEncryptAttributes(type, id, namespace, attributes), - updated_at: time, - ...(Array.isArray(references) && { references }), - }; + updatedOrCreatedSavedObject = { + id, + type, + updated_at: time, + version: encodeHitVersion(createDocResponseBody), + namespaces, + ...(originId && { originId }), + references, + attributes: upsert, // these ignore the attribute values provided in the main request body. + } as SavedObject; - const body = await client - .update({ - id: serializer.generateRawId(namespace, type, id), + // UPSERT CASE END + } else { + // UPDATE CASE START + // at this point, we already know 1. the document exists 2. we're not doing an upsert + // therefor we can safely process with the "standard" update sequence. + + const updatedAttributes = mergeForUpdate( + { ...migrated!.attributes }, + await encryptionHelper.optionallyEncryptAttributes(type, id, namespace, attributes) + ); + const migratedUpdatedSavedObjectDoc = migrationHelper.migrateInputDocument({ + ...migrated!, + id, + type, + // need to override the redacted NS values from the decrypted/migrated document + namespace: savedObjectNamespace, + namespaces: savedObjectNamespaces, + attributes: updatedAttributes, + updated_at: time, + ...(Array.isArray(references) && { references }), + }); + + const docToSend = serializer.savedObjectToRaw( + migratedUpdatedSavedObjectDoc as SavedObjectSanitizedDoc + ); + + // implement creating the call params + const indexRequestParams = { + id: docToSend._id, index: commonHelper.getIndexForType(type), - ...getExpectedVersionProperties(version), refresh, - retry_on_conflict: retryOnConflict, - body: { - doc, - ...(rawUpsert && { upsert: rawUpsert._source }), - }, - _source_includes: ['namespace', 'namespaces', 'originId'], + body: docToSend._source, + // using version from the source doc if not provided as option to avoid erasing changes in case of concurrent calls + ...decodeRequestVersion(version || migrated!.version), require_alias: true, - }) - .catch((err) => { + }; + + const { + body: indexDocResponseBody, + statusCode, + headers, + } = await client.index(indexRequestParams, { meta: true }).catch((err) => { if (SavedObjectsErrorHelpers.isEsUnavailableError(err)) { throw err; } @@ -150,31 +289,50 @@ export const performUpdate = async ( // see "404s from missing index" above throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } + if (SavedObjectsErrorHelpers.isConflictError(err)) { + // flag the error as being caused by an update conflict + err.retryableConflict = true; + } throw err; }); + // throw if we can't verify a 404 response is from Elasticsearch + if (isNotFoundFromUnsupportedServer({ statusCode, headers })) { + throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(id, type); + } + // client.index doesn't return the indexed document. + // Rather than making another round trip to elasticsearch to fetch the doc, we use the SO we sent + // rawToSavedObject adds references as [] if undefined + const updatedSavedObject = serializer.rawToSavedObject( + { + ...docToSend, + ...indexDocResponseBody, + }, + { migrationVersionCompatibility } + ); - const { originId } = body.get?._source ?? {}; - let namespaces: string[] = []; - if (!registry.isNamespaceAgnostic(type)) { - namespaces = body.get?._source.namespaces ?? [ - SavedObjectsUtils.namespaceIdToString(body.get?._source.namespace), - ]; - } + const { originId } = updatedSavedObject ?? {}; + let namespaces: string[] = []; + if (!registry.isNamespaceAgnostic(type)) { + namespaces = updatedSavedObject.namespaces ?? [ + SavedObjectsUtils.namespaceIdToString(updatedSavedObject.namespace), + ]; + } - const result = { - id, - type, - updated_at: time, - version: encodeHitVersion(body), - namespaces, - ...(originId && { originId }), - references, - attributes, - } as SavedObject; + updatedOrCreatedSavedObject = { + id, + type, + updated_at: time, + version: encodeHitVersion(indexDocResponseBody), + namespaces, + ...(originId && { originId }), + references, + attributes, + } as SavedObject; + } return encryptionHelper.optionallyDecryptAndRedactSingleResult( - result, + updatedOrCreatedSavedObject!, authorizationResult?.typeMap, - attributes + shouldPerformUpsert ? upsert : attributes ); }; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/index.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/index.ts index f3562dffb1e86..575b29d47ca0f 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/index.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/index.ts @@ -23,3 +23,4 @@ export { type GetSavedObjectFromSourceOptions, } from './internal_utils'; export { type Left, type Either, type Right, isLeft, isRight, left, right } from './either'; +export { mergeForUpdate } from './merge_for_update'; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.test.ts new file mode 100644 index 0000000000000..7d859f374a5e2 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.test.ts @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { mergeForUpdate } from './merge_for_update'; + +describe('mergeForUpdate', () => { + it('merges top level properties', () => { + expect(mergeForUpdate({ foo: 'bar', hello: 'dolly' }, { baz: 42 })).toEqual({ + foo: 'bar', + hello: 'dolly', + baz: 42, + }); + }); + + it('overrides top level properties', () => { + expect(mergeForUpdate({ foo: 'bar', hello: 'dolly' }, { baz: 42, foo: '9000' })).toEqual({ + foo: '9000', + hello: 'dolly', + baz: 42, + }); + }); + + it('ignores undefined top level properties', () => { + expect(mergeForUpdate({ foo: 'bar', hello: 'dolly' }, { baz: 42, foo: undefined })).toEqual({ + foo: 'bar', + hello: 'dolly', + baz: 42, + }); + }); + + it('merges nested properties', () => { + expect( + mergeForUpdate({ nested: { foo: 'bar', hello: 'dolly' } }, { nested: { baz: 42 } }) + ).toEqual({ + nested: { + foo: 'bar', + hello: 'dolly', + baz: 42, + }, + }); + }); + + it('overrides nested properties', () => { + expect( + mergeForUpdate( + { nested: { foo: 'bar', hello: 'dolly' } }, + { nested: { baz: 42, foo: '9000' } } + ) + ).toEqual({ + nested: { + foo: '9000', + hello: 'dolly', + baz: 42, + }, + }); + }); + + it('ignores undefined nested properties', () => { + expect( + mergeForUpdate( + { nested: { foo: 'bar', hello: 'dolly' } }, + { nested: { baz: 42, foo: undefined } } + ) + ).toEqual({ + nested: { + foo: 'bar', + hello: 'dolly', + baz: 42, + }, + }); + }); + + it('functions with mixed levels of properties', () => { + expect( + mergeForUpdate( + { rootPropA: 'A', nested: { foo: 'bar', hello: 'dolly', deep: { deeper: 'we need' } } }, + { rootPropB: 'B', nested: { baz: 42, foo: '9000', deep: { deeper: 'we are' } } } + ) + ).toEqual({ + rootPropA: 'A', + rootPropB: 'B', + nested: { + foo: '9000', + hello: 'dolly', + baz: 42, + deep: { + deeper: 'we are', + }, + }, + }); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.ts new file mode 100644 index 0000000000000..a3ad081fa74d7 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.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 { isPlainObject } from 'lodash'; +import { set } from '@kbn/safer-lodash-set'; + +export const mergeForUpdate = ( + targetAttributes: Record, + updatedAttributes: any +): Record => { + return recursiveMerge(targetAttributes, updatedAttributes, []); +}; + +const recursiveMerge = (target: Record, value: any, keys: string[] = []) => { + if (isPlainObject(value) && Object.keys(value).length > 0) { + for (const [subKey, subVal] of Object.entries(value)) { + recursiveMerge(target, subVal, [...keys, subKey]); + } + } else if (keys.length > 0 && value !== undefined) { + set(target, keys, value); + } + + return target; +}; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.encryption_extension.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.encryption_extension.test.ts index 9c2c70e27d121..ecaefe05d65e0 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.encryption_extension.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.encryption_extension.test.ts @@ -350,7 +350,7 @@ describe('SavedObjectsRepository Encryption Extension', () => { namespace, } ); - expect(client.update).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledTimes(1); expect(mockEncryptionExt.isEncryptableType).toHaveBeenCalledTimes(2); // (no upsert) optionallyEncryptAttributes, optionallyDecryptAndRedactSingleResult expect(mockEncryptionExt.isEncryptableType).toHaveBeenCalledWith(nonEncryptedSO.type); expect(mockEncryptionExt.encryptAttributes).not.toHaveBeenCalled(); @@ -382,7 +382,7 @@ describe('SavedObjectsRepository Encryption Extension', () => { references: encryptedSO.references, } ); - expect(client.update).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledTimes(1); expect(mockEncryptionExt.isEncryptableType).toHaveBeenCalledTimes(2); // (no upsert) optionallyEncryptAttributes, optionallyDecryptAndRedactSingleResult expect(mockEncryptionExt.isEncryptableType).toHaveBeenCalledWith(encryptedSO.type); expect(mockEncryptionExt.encryptAttributes).toHaveBeenCalledTimes(1); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.security_extension.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.security_extension.test.ts index 3e81c09d1df9f..30778ef7b5f92 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.security_extension.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.security_extension.test.ts @@ -235,7 +235,7 @@ describe('SavedObjectsRepository Security Extension', () => { }); expect(mockSecurityExt.authorizeUpdate).toHaveBeenCalledTimes(1); - expect(client.update).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledTimes(1); expect(result).toEqual( expect.objectContaining({ id, type, attributes, namespaces: [namespace] }) ); @@ -250,7 +250,7 @@ describe('SavedObjectsRepository Security Extension', () => { }); expect(mockSecurityExt.authorizeUpdate).toHaveBeenCalledTimes(1); - expect(client.update).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledTimes(1); expect(result).toEqual( expect.objectContaining({ id, type, attributes, namespaces: [namespace] }) ); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.spaces_extension.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.spaces_extension.test.ts index a000384ce5236..29983177adc99 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.spaces_extension.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.spaces_extension.test.ts @@ -222,27 +222,26 @@ describe('SavedObjectsRepository Spaces Extension', () => { id, {}, { upsert: true }, - { mockGetResponseValue: { found: false } as estypes.GetResponse } + { mockGetResponseAsNotFound: { found: false } as estypes.GetResponse }, + [currentSpace.expectedNamespace ?? 'default'] ); expect(mockSpacesExt.getCurrentNamespace).toBeCalledTimes(1); expect(mockSpacesExt.getCurrentNamespace).toHaveBeenCalledWith(undefined); - expect(client.update).toHaveBeenCalledTimes(1); - expect(client.update).toHaveBeenCalledWith( + expect(client.create).toHaveBeenCalledTimes(1); + expect(client.create).toHaveBeenCalledWith( expect.objectContaining({ id: `${ currentSpace.expectedNamespace ? `${currentSpace.expectedNamespace}:` : '' }${type}:${id}`, - body: expect.objectContaining({ - upsert: expect.objectContaining( - currentSpace.expectedNamespace - ? { - namespace: currentSpace.expectedNamespace, - } - : {} - ), - }), + body: expect.objectContaining( + currentSpace.expectedNamespace + ? { + namespace: currentSpace.expectedNamespace, + } + : {} + ), }), - { maxRetries: 0 } + expect.any(Object) ); }); }); @@ -1078,7 +1077,8 @@ describe('SavedObjectsRepository Spaces Extension', () => { id, {}, { upsert: true }, - { mockGetResponseValue: { found: false } as estypes.GetResponse } + { mockGetResponseAsNotFound: { found: false } as estypes.GetResponse }, + [currentSpace] ); expect(mockSpacesExt.getCurrentNamespace).toBeCalledTimes(1); expect(mockSpacesExt.getCurrentNamespace).toHaveBeenCalledWith(undefined); @@ -1354,11 +1354,12 @@ describe('SavedObjectsRepository Spaces Extension', () => { { // no namespace provided references: encryptedSO.references, - } + }, + {} ); expect(mockSpacesExt.getCurrentNamespace).toBeCalledTimes(1); expect(mockSpacesExt.getCurrentNamespace).toHaveBeenCalledWith(undefined); - expect(client.update).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledTimes(1); expect(mockEncryptionExt.isEncryptableType).toHaveBeenCalledTimes(2); // (no upsert) optionallyEncryptAttributes, optionallyDecryptAndRedactSingleResult expect(mockEncryptionExt.isEncryptableType).toHaveBeenCalledWith(encryptedSO.type); expect(mockEncryptionExt.encryptAttributes).toHaveBeenCalledTimes(1); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts index ab41890d36368..fa1fda60d09fd 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts @@ -69,7 +69,6 @@ import { import { kibanaMigratorMock } from '../mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; import * as esKuery from '@kbn/es-query'; -import { errors as EsErrors } from '@elastic/elasticsearch'; import { CUSTOM_INDEX_TYPE, @@ -94,8 +93,6 @@ import { getMockBulkCreateResponse, bulkGet, getMockBulkUpdateResponse, - updateSuccess, - mockUpdateResponse, expectErrorResult, expectErrorInvalidType, expectErrorNotFound, @@ -188,6 +185,7 @@ describe('SavedObjectsRepository', () => { mockGetSearchDsl.mockClear(); }); + // Setup migration mock for creating an object const mockMigrationVersion = { foo: '2.3.4' }; const mockMigrateDocument = (doc: SavedObjectUnsanitizedDoc) => ({ ...doc, @@ -4819,507 +4817,6 @@ describe('SavedObjectsRepository', () => { }); }); - describe('#update', () => { - const id = 'logstash-*'; - const type = 'index-pattern'; - const attributes = { title: 'Testing' }; - const namespace = 'foo-namespace'; - const references = [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ]; - const originId = 'some-origin-id'; - - beforeEach(() => { - mockPreflightCheckForCreate.mockReset(); - mockPreflightCheckForCreate.mockImplementation(({ objects }) => { - return Promise.resolve(objects.map(({ type, id }) => ({ type, id }))); // respond with no errors by default - }); - }); - - describe('client calls', () => { - it(`should use the ES update action when type is not multi-namespace`, async () => { - await updateSuccess(client, repository, registry, type, id, attributes); - expect(client.get).not.toHaveBeenCalled(); - expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); - expect(client.update).toHaveBeenCalledTimes(1); - }); - - it(`should use the ES get action then update action when type is multi-namespace`, async () => { - await updateSuccess( - client, - repository, - registry, - MULTI_NAMESPACE_ISOLATED_TYPE, - id, - attributes - ); - expect(client.get).toHaveBeenCalledTimes(1); - expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); - expect(client.update).toHaveBeenCalledTimes(1); - }); - - it(`should check for alias conflicts if a new multi-namespace object would be created`, async () => { - await updateSuccess( - client, - repository, - registry, - MULTI_NAMESPACE_ISOLATED_TYPE, - id, - attributes, - { upsert: true }, - { mockGetResponseValue: { found: false } as estypes.GetResponse } - ); - expect(client.get).toHaveBeenCalledTimes(1); - expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); - expect(client.update).toHaveBeenCalledTimes(1); - }); - - it(`defaults to no references array`, async () => { - await updateSuccess(client, repository, registry, type, id, attributes); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ - body: { doc: expect.not.objectContaining({ references: expect.anything() }) }, - }), - expect.anything() - ); - }); - - it(`accepts custom references array`, async () => { - const test = async (references: SavedObjectReference[]) => { - await updateSuccess(client, repository, registry, type, id, attributes, { references }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ - body: { doc: expect.objectContaining({ references }) }, - }), - expect.anything() - ); - client.update.mockClear(); - }; - await test(references); - await test([{ type: 'foo', id: '42', name: 'some ref' }]); - await test([]); - }); - - it(`uses the 'upsertAttributes' option when specified for a single-namespace type`, async () => { - await updateSuccess(client, repository, registry, type, id, attributes, { - upsert: { - title: 'foo', - description: 'bar', - }, - }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ - id: 'index-pattern:logstash-*', - body: expect.objectContaining({ - upsert: expect.objectContaining({ - type: 'index-pattern', - 'index-pattern': { - title: 'foo', - description: 'bar', - }, - }), - }), - }), - expect.anything() - ); - }); - - it(`uses the 'upsertAttributes' option when specified for a multi-namespace type that does not exist`, async () => { - const options = { upsert: { title: 'foo', description: 'bar' } }; - mockUpdateResponse(client, MULTI_NAMESPACE_ISOLATED_TYPE, id, options); - await repository.update(MULTI_NAMESPACE_ISOLATED_TYPE, id, attributes, options); - expect(client.get).toHaveBeenCalledTimes(1); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ - id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:logstash-*`, - body: expect.objectContaining({ - upsert: expect.objectContaining({ - type: MULTI_NAMESPACE_ISOLATED_TYPE, - [MULTI_NAMESPACE_ISOLATED_TYPE]: { - title: 'foo', - description: 'bar', - }, - }), - }), - }), - expect.anything() - ); - }); - - it(`ignores use the 'upsertAttributes' option when specified for a multi-namespace type that already exists`, async () => { - const options = { upsert: { title: 'foo', description: 'bar' } }; - await updateSuccess( - client, - repository, - registry, - MULTI_NAMESPACE_ISOLATED_TYPE, - id, - attributes, - options - ); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ - id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:logstash-*`, - body: expect.not.objectContaining({ - upsert: expect.anything(), - }), - }), - expect.anything() - ); - }); - - it(`doesn't accept custom references if not an array`, async () => { - const test = async (references: unknown) => { - // @ts-expect-error references is unknown - await updateSuccess(client, repository, registry, type, id, attributes, { references }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ - body: { doc: expect.not.objectContaining({ references: expect.anything() }) }, - }), - expect.anything() - ); - client.update.mockClear(); - }; - await test('string'); - await test(123); - await test(true); - await test(null); - }); - - it(`defaults to a refresh setting of wait_for`, async () => { - await updateSuccess(client, repository, registry, type, id, { foo: 'bar' }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ - refresh: 'wait_for', - }), - expect.anything() - ); - }); - - it(`does not default to the version of the existing document when type is multi-namespace`, async () => { - await updateSuccess( - client, - repository, - registry, - MULTI_NAMESPACE_ISOLATED_TYPE, - id, - attributes, - { references } - ); - const versionProperties = { - if_seq_no: mockVersionProps._seq_no, - if_primary_term: mockVersionProps._primary_term, - }; - expect(client.update).toHaveBeenCalledWith( - expect.not.objectContaining(versionProperties), - expect.anything() - ); - }); - - it(`accepts version`, async () => { - await updateSuccess(client, repository, registry, type, id, attributes, { - version: encodeHitVersion({ _seq_no: 100, _primary_term: 200 }), - }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ if_seq_no: 100, if_primary_term: 200 }), - expect.anything() - ); - }); - - it('default to a `retry_on_conflict` setting of `3` when `version` is not provided', async () => { - await updateSuccess(client, repository, registry, type, id, attributes, {}); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ retry_on_conflict: 3 }), - expect.anything() - ); - }); - - it('default to a `retry_on_conflict` setting of `0` when `version` is provided', async () => { - await updateSuccess(client, repository, registry, type, id, attributes, { - version: encodeHitVersion({ _seq_no: 100, _primary_term: 200 }), - }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ retry_on_conflict: 0, if_seq_no: 100, if_primary_term: 200 }), - expect.anything() - ); - }); - - it('accepts a `retryOnConflict` option', async () => { - await updateSuccess(client, repository, registry, type, id, attributes, { - version: encodeHitVersion({ _seq_no: 100, _primary_term: 200 }), - retryOnConflict: 42, - }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ retry_on_conflict: 42, if_seq_no: 100, if_primary_term: 200 }), - expect.anything() - ); - }); - - it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { - await updateSuccess(client, repository, registry, type, id, attributes, { namespace }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ id: expect.stringMatching(`${namespace}:${type}:${id}`) }), - expect.anything() - ); - }); - - it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { - await updateSuccess(client, repository, registry, type, id, attributes, { references }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ id: expect.stringMatching(`${type}:${id}`) }), - expect.anything() - ); - }); - - it(`normalizes options.namespace from 'default' to undefined`, async () => { - await updateSuccess(client, repository, registry, type, id, attributes, { - references, - namespace: 'default', - }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ id: expect.stringMatching(`${type}:${id}`) }), - expect.anything() - ); - }); - - it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { - await updateSuccess(client, repository, registry, NAMESPACE_AGNOSTIC_TYPE, id, attributes, { - namespace, - }); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ - id: expect.stringMatching(`${NAMESPACE_AGNOSTIC_TYPE}:${id}`), - }), - expect.anything() - ); - - client.update.mockClear(); - await updateSuccess( - client, - repository, - registry, - MULTI_NAMESPACE_ISOLATED_TYPE, - id, - attributes, - { namespace } - ); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ - id: expect.stringMatching(`${MULTI_NAMESPACE_ISOLATED_TYPE}:${id}`), - }), - expect.anything() - ); - }); - - it(`includes _source_includes when type is multi-namespace`, async () => { - await updateSuccess( - client, - repository, - registry, - MULTI_NAMESPACE_ISOLATED_TYPE, - id, - attributes - ); - expect(client.update).toHaveBeenCalledWith( - expect.objectContaining({ _source_includes: ['namespace', 'namespaces', 'originId'] }), - expect.anything() - ); - }); - - it(`includes _source_includes when type is not multi-namespace`, async () => { - await updateSuccess(client, repository, registry, type, id, attributes); - expect(client.update).toHaveBeenLastCalledWith( - expect.objectContaining({ - _source_includes: ['namespace', 'namespaces', 'originId'], - }), - expect.anything() - ); - }); - }); - - describe('errors', () => { - const expectNotFoundError = async (type: string, id: string) => { - await expect(repository.update(type, id, {})).rejects.toThrowError( - createGenericNotFoundErrorPayload(type, id) - ); - }; - - it(`throws when options.namespace is '*'`, async () => { - await expect( - repository.update(type, id, attributes, { namespace: ALL_NAMESPACES_STRING }) - ).rejects.toThrowError(createBadRequestErrorPayload('"options.namespace" cannot be "*"')); - }); - - it(`throws when type is invalid`, async () => { - await expectNotFoundError('unknownType', id); - expect(client.update).not.toHaveBeenCalled(); - }); - - it(`throws when type is hidden`, async () => { - await expectNotFoundError(HIDDEN_TYPE, id); - expect(client.update).not.toHaveBeenCalled(); - }); - - it(`throws when id is empty`, async () => { - await expect(repository.update(type, '', attributes)).rejects.toThrowError( - createBadRequestErrorPayload('id cannot be empty') - ); - expect(client.update).not.toHaveBeenCalled(); - }); - - it(`throws when ES is unable to find the document during get`, async () => { - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { found: false } as estypes.GetResponse, - undefined - ) - ); - await expectNotFoundError(MULTI_NAMESPACE_ISOLATED_TYPE, id); - expect(client.get).toHaveBeenCalledTimes(1); - }); - - it(`throws when ES is unable to find the index during get`, async () => { - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise({} as estypes.GetResponse, { - statusCode: 404, - }) - ); - await expectNotFoundError(MULTI_NAMESPACE_ISOLATED_TYPE, id); - expect(client.get).toHaveBeenCalledTimes(1); - }); - - it(`throws when type is multi-namespace and the document exists, but not in this namespace`, async () => { - const response = getMockGetResponse( - registry, - { type: MULTI_NAMESPACE_ISOLATED_TYPE, id }, - namespace - ); - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(response) - ); - await expectNotFoundError(MULTI_NAMESPACE_ISOLATED_TYPE, id); - expect(client.get).toHaveBeenCalledTimes(1); - }); - - it(`throws when there is an alias conflict from preflightCheckForCreate`, async () => { - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise({ - found: false, - } as estypes.GetResponse) - ); - mockPreflightCheckForCreate.mockResolvedValue([ - { type: 'type', id: 'id', error: { type: 'aliasConflict' } }, - ]); - await expect( - repository.update( - MULTI_NAMESPACE_ISOLATED_TYPE, - id, - { attr: 'value' }, - { - upsert: { - upsertAttr: 'val', - attr: 'value', - }, - } - ) - ).rejects.toThrowError(createConflictErrorPayload(MULTI_NAMESPACE_ISOLATED_TYPE, id)); - expect(client.get).toHaveBeenCalledTimes(1); - expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); - expect(client.update).not.toHaveBeenCalled(); - }); - - it(`does not throw when there is a different error from preflightCheckForCreate`, async () => { - mockPreflightCheckForCreate.mockResolvedValue([ - { type: 'type', id: 'id', error: { type: 'conflict' } }, - ]); - await updateSuccess( - client, - repository, - registry, - MULTI_NAMESPACE_ISOLATED_TYPE, - id, - attributes, - { upsert: true }, - { mockGetResponseValue: { found: false } as estypes.GetResponse } - ); - expect(client.get).toHaveBeenCalledTimes(1); - expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); - expect(client.update).toHaveBeenCalledTimes(1); - }); - - it(`throws when ES is unable to find the document during update`, async () => { - const notFoundError = new EsErrors.ResponseError( - elasticsearchClientMock.createApiResponse({ - statusCode: 404, - body: { error: { type: 'es_type', reason: 'es_reason' } }, - }) - ); - client.update.mockResolvedValueOnce( - elasticsearchClientMock.createErrorTransportRequestPromise(notFoundError) - ); - await expectNotFoundError(type, id); - expect(client.update).toHaveBeenCalledTimes(1); - }); - }); - - describe('returns', () => { - it(`returns _seq_no and _primary_term encoded as version`, async () => { - const result = await updateSuccess(client, repository, registry, type, id, attributes, { - namespace, - references, - }); - expect(result).toEqual({ - id, - type, - ...mockTimestampFields, - version: mockVersion, - attributes, - references, - namespaces: [namespace], - }); - }); - - it(`includes namespaces if type is multi-namespace`, async () => { - const result = await updateSuccess( - client, - repository, - registry, - MULTI_NAMESPACE_ISOLATED_TYPE, - id, - attributes - ); - expect(result).toMatchObject({ - namespaces: expect.any(Array), - }); - }); - - it(`includes namespaces if type is not multi-namespace`, async () => { - const result = await updateSuccess(client, repository, registry, type, id, attributes); - expect(result).toMatchObject({ - namespaces: ['default'], - }); - }); - - it(`includes originId property if present in cluster call response`, async () => { - const result = await updateSuccess( - client, - repository, - registry, - type, - id, - attributes, - {}, - { originId } - ); - expect(result).toMatchObject({ originId }); - }); - }); - }); - describe('#openPointInTimeForType', () => { const type = 'index-pattern'; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/utils/index.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/utils/index.ts index ba96c10da0090..861a2f847d97b 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/utils/index.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/utils/index.ts @@ -9,3 +9,4 @@ export { decorateEsError } from './decorate_es_error'; export { getRootFields, includedFields } from './included_fields'; export { createRepositoryHelpers } from './create_helpers'; +export { isValidRequest } from './update_utils'; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/utils/update_utils.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/utils/update_utils.ts new file mode 100644 index 0000000000000..c686cbb7ca68b --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/utils/update_utils.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { SavedObjectsErrorHelpers } from '@kbn/core-saved-objects-server'; + +export const isValidRequest = ({ + allowedTypes, + type, + id, +}: { + allowedTypes: string[]; + type: string; + id?: string; +}) => { + return !id + ? { + validRequest: false, + error: SavedObjectsErrorHelpers.createBadRequestError('id cannot be empty'), + } + : !allowedTypes.includes(type) + ? { + validRequest: false, + error: SavedObjectsErrorHelpers.createGenericNotFoundError(type, id), + } + : { + validRequest: true, + }; +}; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/mocks/api_helpers.mocks.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/mocks/api_helpers.mocks.ts index 69f0124f681e1..e50cc4d1036eb 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/mocks/api_helpers.mocks.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/mocks/api_helpers.mocks.ts @@ -92,6 +92,8 @@ const createPreflightCheckHelperMock = (): PreflightCheckHelperMock => { preflightCheckForBulkDelete: jest.fn(), preflightCheckNamespaces: jest.fn(), preflightCheckForUpsertAliasConflict: jest.fn(), + preflightGetDocForUpdate: jest.fn(), + preflightCheckNamespacesForUpdate: jest.fn(), }; return mock; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/test_helpers/repository.test.common.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/test_helpers/repository.test.common.ts index 2cb4f32f441cb..29c00e9d41ac1 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/test_helpers/repository.test.common.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/test_helpers/repository.test.common.ts @@ -103,7 +103,7 @@ export const expectErrorConflict = (obj: TypeIdTuple, overrides?: Record) => expectErrorResult(obj, createUnsupportedTypeErrorPayload(obj.type), overrides); -export const KIBANA_VERSION = '2.0.0'; +export const KIBANA_VERSION = '8.8.0'; export const ALLOWED_CONVERT_VERSION = '8.0.0'; export const CUSTOM_INDEX_TYPE = 'customIndex'; /** This type has namespaceType: 'agnostic'. */ @@ -439,7 +439,7 @@ export const getMockGetResponse = ( } const namespaceId = namespaces[0] === 'default' ? undefined : namespaces[0]; - return { + const result = { // NOTE: Elasticsearch returns more fields (_index, _type) but the SavedObjectsRepository method ignores these found: true, _id: `${registry.isSingleNamespace(type) && namespaceId ? `${namespaceId}:` : ''}${type}:${id}`, @@ -464,6 +464,7 @@ export const getMockGetResponse = ( ...mockTimestampFields, } as SavedObjectsRawDocSource, } as estypes.GetResponse; + return result; }; export const getMockMgetResponse = ( @@ -489,35 +490,6 @@ expect.extend({ }, }); -export const mockUpdateResponse = ( - client: ElasticsearchClientMock, - type: string, - id: string, - options?: SavedObjectsUpdateOptions, - namespaces?: string[], - originId?: string -) => { - client.update.mockResponseOnce( - { - _id: `${type}:${id}`, - ...mockVersionProps, - result: 'updated', - // don't need the rest of the source for test purposes, just the namespace and namespaces attributes - get: { - _source: { - namespaces: namespaces ?? [options?.namespace ?? 'default'], - namespace: options?.namespace, - - // If the existing saved object contains an originId attribute, the operation will return it in the result. - // The originId parameter is just used for test purposes to modify the mock cluster call response. - ...(!!originId && { originId }), - }, - }, - } as estypes.UpdateResponse, - { statusCode: 200 } - ); -}; - export const updateSuccess = async >( client: ElasticsearchClientMock, repository: SavedObjectsRepository, @@ -528,20 +500,40 @@ export const updateSuccess = async >( options?: SavedObjectsUpdateOptions, internalOptions: { originId?: string; - mockGetResponseValue?: estypes.GetResponse; + mockGetResponseAsNotFound?: estypes.GetResponse; } = {}, objNamespaces?: string[] ) => { - const { mockGetResponseValue, originId } = internalOptions; - if (registry.isMultiNamespace(type)) { - const mockGetResponse = - mockGetResponseValue ?? - getMockGetResponse(registry, { type, id }, objNamespaces ?? options?.namespace); - client.get.mockResponseOnce(mockGetResponse, { statusCode: 200 }); + const { mockGetResponseAsNotFound, originId } = internalOptions; + const mockGetResponse = + mockGetResponseAsNotFound ?? + getMockGetResponse(registry, { type, id, originId }, objNamespaces ?? options?.namespace); + client.get.mockResponseOnce(mockGetResponse, { statusCode: 200 }); + if (!mockGetResponseAsNotFound) { + // index doc from existing doc + client.index.mockResponseImplementation((params) => { + return { + body: { + _id: params.id, + ...mockVersionProps, + } as estypes.CreateResponse, + }; + }); + } + if (mockGetResponseAsNotFound) { + // upsert case: create the doc. (be careful here, we're also sending mockGetResponseValue as { found: false }) + client.create.mockResponseImplementation((params) => { + return { + body: { + _id: params.id, + ...mockVersionProps, + } as estypes.CreateResponse, + }; + }); } - mockUpdateResponse(client, type, id, options, objNamespaces, originId); + const result = await repository.update(type, id, attributes, options); - expect(client.get).toHaveBeenCalledTimes(registry.isMultiNamespace(type) ? 1 : 0); + expect(client.get).toHaveBeenCalled(); // not asserting on the number of calls here, we end up testing the test mocks and not the actual implementation return result; }; diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/update.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/update.ts index 66f7103102b6e..e830b32601c5b 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/update.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/update.ts @@ -18,6 +18,7 @@ export interface SavedObjectsUpdateOptions extends SavedOb /** * An opaque version number which changes on each successful write operation. * Can be used for implementing optimistic concurrency control. + * Unused for multi-namespace objects */ version?: string; /** {@inheritdoc SavedObjectReference} */ @@ -31,6 +32,8 @@ export interface SavedObjectsUpdateOptions extends SavedOb * Defaults to `0` when `version` is provided, `3` otherwise. */ retryOnConflict?: number; + /** {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} */ + migrationVersionCompatibility?: 'compatible' | 'raw'; } /** diff --git a/packages/core/saved-objects/core-saved-objects-base-server-internal/src/serialization/serializer.ts b/packages/core/saved-objects/core-saved-objects-base-server-internal/src/serialization/serializer.ts index 96eded287975c..cb3036fa9d668 100644 --- a/packages/core/saved-objects/core-saved-objects-base-server-internal/src/serialization/serializer.ts +++ b/packages/core/saved-objects/core-saved-objects-base-server-internal/src/serialization/serializer.ts @@ -116,7 +116,7 @@ export class SavedObjectsSerializer implements ISavedObjectsSerializer { ...(includeNamespaces && { namespaces }), ...(originId && { originId }), attributes: _source[type], - references: references || [], + references: references || [], // adds references default ...(managed != null ? { managed } : {}), ...(migrationVersion && { migrationVersion }), ...(coreMigrationVersion && { coreMigrationVersion }), diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap index fffab519cbf3d..d513177d685bc 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap @@ -25,6 +25,9 @@ Object { "currentAlias": ".my-so-index", "discardCorruptObjects": false, "discardUnknownObjects": false, + "esCapabilities": Object { + "serverless": false, + }, "excludeFromUpgradeFilterHooks": Object {}, "excludeOnUpgradeQuery": Object { "bool": Object { @@ -250,6 +253,9 @@ Object { "currentAlias": ".my-so-index", "discardCorruptObjects": false, "discardUnknownObjects": false, + "esCapabilities": Object { + "serverless": false, + }, "excludeFromUpgradeFilterHooks": Object {}, "excludeOnUpgradeQuery": Object { "bool": Object { @@ -479,6 +485,9 @@ Object { "currentAlias": ".my-so-index", "discardCorruptObjects": false, "discardUnknownObjects": false, + "esCapabilities": Object { + "serverless": false, + }, "excludeFromUpgradeFilterHooks": Object {}, "excludeOnUpgradeQuery": Object { "bool": Object { @@ -712,6 +721,9 @@ Object { "currentAlias": ".my-so-index", "discardCorruptObjects": false, "discardUnknownObjects": false, + "esCapabilities": Object { + "serverless": false, + }, "excludeFromUpgradeFilterHooks": Object {}, "excludeOnUpgradeQuery": Object { "bool": Object { @@ -981,6 +993,9 @@ Object { "currentAlias": ".my-so-index", "discardCorruptObjects": false, "discardUnknownObjects": false, + "esCapabilities": Object { + "serverless": false, + }, "excludeFromUpgradeFilterHooks": Object {}, "excludeOnUpgradeQuery": Object { "bool": Object { @@ -1217,6 +1232,9 @@ Object { "currentAlias": ".my-so-index", "discardCorruptObjects": false, "discardUnknownObjects": false, + "esCapabilities": Object { + "serverless": false, + }, "excludeFromUpgradeFilterHooks": Object {}, "excludeOnUpgradeQuery": Object { "bool": Object { diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.test.ts index 49e20d7fc7b39..73cba7294aa63 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.test.ts @@ -8,8 +8,8 @@ import { errors as EsErrors } from '@elastic/elasticsearch'; import { cloneIndex } from './clone_index'; -import { setWriteBlock } from './set_write_block'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors'; jest.mock('./catch_retryable_es_client_errors'); @@ -36,11 +36,82 @@ describe('cloneIndex', () => { elasticsearchClientMock.createErrorTransportRequestPromise(nonRetryableError) ); + it('calls client.indices.clone with the correct parameter for default ES', async () => { + const statefulCapabilities = elasticsearchServiceMock.createCapabilities({ serverless: false }); + const task = cloneIndex({ + client, + source: 'my_source_index', + target: 'my_target_index', + esCapabilities: statefulCapabilities, + }); + try { + await task(); + } catch (e) { + /** ignore */ + } + expect(client.indices.clone.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "index": "my_source_index", + "settings": Object { + "index": Object { + "auto_expand_replicas": "0-1", + "blocks.write": false, + "mapping": Object { + "total_fields": Object { + "limit": 1500, + }, + }, + "number_of_shards": 1, + "priority": 10, + "refresh_interval": "1s", + }, + }, + "target": "my_target_index", + "timeout": "60s", + "wait_for_active_shards": "all", + } + `); + }); + + it('calls client.indices.clone with the correct parameter for serverless ES', async () => { + const statelessCapabilities = elasticsearchServiceMock.createCapabilities({ serverless: true }); + const task = cloneIndex({ + client, + source: 'my_source_index', + target: 'my_target_index', + esCapabilities: statelessCapabilities, + }); + try { + await task(); + } catch (e) { + /** ignore */ + } + expect(client.indices.clone.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "index": "my_source_index", + "settings": Object { + "index": Object { + "blocks.write": false, + "mapping": Object { + "total_fields": Object { + "limit": 1500, + }, + }, + }, + }, + "target": "my_target_index", + "timeout": "60s", + "wait_for_active_shards": "all", + } + `); + }); + it('calls catchRetryableEsClientErrors when the promise rejects', async () => { const task = cloneIndex({ client, source: 'my_source_index', target: 'my_target_index', + esCapabilities: elasticsearchServiceMock.createCapabilities(), }); try { await task(); @@ -51,11 +122,17 @@ describe('cloneIndex', () => { }); it('re-throws non retry-able errors', async () => { - const task = setWriteBlock({ + const task = cloneIndex({ client: clientWithNonRetryableError, - index: 'my_index', + source: 'my_source_index', + target: 'my_target_index', + esCapabilities: elasticsearchServiceMock.createCapabilities(), }); - await task(); + try { + await task(); + } catch (e) { + /** ignore */ + } expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(nonRetryableError); }); }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.ts index 41830a4af078e..9bce341d242b3 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/clone_index.ts @@ -10,7 +10,10 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; import { pipe } from 'fp-ts/lib/pipeable'; import { errors as EsErrors } from '@elastic/elasticsearch'; -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ElasticsearchClient, + ElasticsearchCapabilities, +} from '@kbn/core-elasticsearch-server'; import { catchRetryableEsClientErrors, type RetryableEsClientError, @@ -31,11 +34,13 @@ export type CloneIndexResponse = AcknowledgeResponse; /** @internal */ export interface CloneIndexParams { client: ElasticsearchClient; + esCapabilities: ElasticsearchCapabilities; source: string; target: string; /** only used for testing */ timeout?: string; } + /** * Makes a clone of the source index into the target. * @@ -48,6 +53,7 @@ export interface CloneIndexParams { */ export const cloneIndex = ({ client, + esCapabilities, source, target, timeout = DEFAULT_TIMEOUT, @@ -59,16 +65,18 @@ export const cloneIndex = ({ RetryableEsClientError | IndexNotFound | ClusterShardLimitExceeded, AcknowledgeResponse > = () => { - return client.indices - .clone({ - index: source, - target, - wait_for_active_shards: WAIT_FOR_ALL_SHARDS_TO_BE_ACTIVE, - settings: { - index: { - // The source we're cloning from will have a write block set, so - // we need to remove it to allow writes to our newly cloned index - 'blocks.write': false, + const indexSettings = { + // The source we're cloning from will have a write block set, so + // we need to remove it to allow writes to our newly cloned index + 'blocks.write': false, + // Increase the fields limit beyond the default of 1000 + mapping: { + total_fields: { limit: 1500 }, + }, + // settings not being supported on serverless ES + ...(esCapabilities.serverless + ? {} + : { // The rest of the index settings should have already been applied // to the source index and will be copied to the clone target. But // we repeat it here for explicitness. @@ -80,11 +88,16 @@ export const cloneIndex = ({ refresh_interval: '1s', // Bump priority so that recovery happens before newer indices priority: 10, - // Increase the fields limit beyond the default of 1000 - mapping: { - total_fields: { limit: 1500 }, - }, - }, + }), + }; + + return client.indices + .clone({ + index: source, + target, + wait_for_active_shards: WAIT_FOR_ALL_SHARDS_TO_BE_ACTIVE, + settings: { + index: indexSettings, }, timeout, }) diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.test.ts index 47ea28ca2953d..d34970e902e31 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.test.ts @@ -9,8 +9,8 @@ import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors'; import { errors as EsErrors } from '@elastic/elasticsearch'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import { createIndex } from './create_index'; -import { setWriteBlock } from './set_write_block'; jest.mock('./catch_retryable_es_client_errors'); @@ -35,11 +35,87 @@ describe('createIndex', () => { const clientWithNonRetryableError = elasticsearchClientMock.createInternalClient( elasticsearchClientMock.createErrorTransportRequestPromise(nonRetryableError) ); + + it('calls client.indices.create with the correct parameter for default ES', async () => { + const statefulCapabilities = elasticsearchServiceMock.createCapabilities({ serverless: false }); + const task = createIndex({ + client, + indexName: 'my_index', + mappings: { properties: {} }, + esCapabilities: statefulCapabilities, + }); + try { + await task(); + } catch (e) { + /** ignore */ + } + expect(client.indices.create.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "aliases": Object {}, + "index": "my_index", + "mappings": Object { + "properties": Object {}, + }, + "settings": Object { + "index": Object { + "auto_expand_replicas": "0-1", + "mapping": Object { + "total_fields": Object { + "limit": 1500, + }, + }, + "number_of_shards": 1, + "priority": 10, + "refresh_interval": "1s", + }, + }, + "timeout": "60s", + "wait_for_active_shards": "all", + } + `); + }); + + it('calls client.indices.create with the correct parameter for serverless ES', async () => { + const statelessCapabilities = elasticsearchServiceMock.createCapabilities({ serverless: true }); + const task = createIndex({ + client, + indexName: 'my_index', + mappings: { properties: {} }, + esCapabilities: statelessCapabilities, + }); + try { + await task(); + } catch (e) { + /** ignore */ + } + expect(client.indices.create.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "aliases": Object {}, + "index": "my_index", + "mappings": Object { + "properties": Object {}, + }, + "settings": Object { + "index": Object { + "mapping": Object { + "total_fields": Object { + "limit": 1500, + }, + }, + }, + }, + "timeout": "60s", + "wait_for_active_shards": "all", + } + `); + }); + it('calls catchRetryableEsClientErrors when the promise rejects', async () => { const task = createIndex({ client, indexName: 'new_index', mappings: { properties: {} }, + esCapabilities: elasticsearchServiceMock.createCapabilities(), }); try { await task(); @@ -49,12 +125,19 @@ describe('createIndex', () => { expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(retryableError); }); + it('re-throws non retry-able errors', async () => { - const task = setWriteBlock({ + const task = createIndex({ client: clientWithNonRetryableError, - index: 'my_index', + indexName: 'my_index', + mappings: { properties: {} }, + esCapabilities: elasticsearchServiceMock.createCapabilities(), }); - await task(); + try { + await task(); + } catch (e) { + /** ignore */ + } expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(nonRetryableError); }); }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.ts index 1d492301f45bd..df4239390ee39 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/create_index.ts @@ -10,7 +10,10 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; import { pipe } from 'fp-ts/lib/pipeable'; import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ElasticsearchClient, + ElasticsearchCapabilities, +} from '@kbn/core-elasticsearch-server'; import type { IndexMapping } from '@kbn/core-saved-objects-base-server-internal'; import { catchRetryableEsClientErrors, @@ -19,6 +22,7 @@ import { import { DEFAULT_TIMEOUT, INDEX_AUTO_EXPAND_REPLICAS, + INDEX_NUMBER_OF_SHARDS, WAIT_FOR_ALL_SHARDS_TO_BE_ACTIVE, } from './constants'; import { type IndexNotGreenTimeout, waitForIndexStatus } from './wait_for_index_status'; @@ -42,6 +46,7 @@ export interface CreateIndexParams { client: ElasticsearchClient; indexName: string; mappings: IndexMapping; + esCapabilities: ElasticsearchCapabilities; aliases?: string[]; timeout?: string; } @@ -62,6 +67,7 @@ export const createIndex = ({ client, indexName, mappings, + esCapabilities, aliases = [], timeout = DEFAULT_TIMEOUT, }: CreateIndexParams): TaskEither.TaskEither< @@ -74,6 +80,28 @@ export const createIndex = ({ > = () => { const aliasesObject = aliasArrayToRecord(aliases); + const indexSettings = { + // settings not being supported on serverless ES + ...(esCapabilities.serverless + ? {} + : { + // ES rule of thumb: shards should be several GB to 10's of GB, so + // Kibana is unlikely to cross that limit. + number_of_shards: INDEX_NUMBER_OF_SHARDS, + auto_expand_replicas: INDEX_AUTO_EXPAND_REPLICAS, + // Set an explicit refresh interval so that we don't inherit the + // value from incorrectly configured index templates (not required + // after we adopt system indices) + refresh_interval: '1s', + // Bump priority so that recovery happens before newer indices + priority: 10, + }), + // Increase the fields limit beyond the default of 1000 + mapping: { + total_fields: { limit: 1500 }, + }, + }; + return client.indices .create({ index: indexName, @@ -87,22 +115,7 @@ export const createIndex = ({ mappings, aliases: aliasesObject, settings: { - index: { - // ES rule of thumb: shards should be several GB to 10's of GB, so - // Kibana is unlikely to cross that limit. - number_of_shards: 1, - auto_expand_replicas: INDEX_AUTO_EXPAND_REPLICAS, - // Set an explicit refresh interval so that we don't inherit the - // value from incorrectly configured index templates (not required - // after we adopt system indices) - refresh_interval: '1s', - // Bump priority so that recovery happens before newer indices - priority: 10, - // Increase the fields limit beyond the default of 1000 - mapping: { - total_fields: { limit: 1500 }, - }, - }, + index: indexSettings, }, }) .then(() => { diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts index 31c0b1fc5e9fd..e173def8da914 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts @@ -17,6 +17,7 @@ import { } from '@kbn/core-saved-objects-base-server-internal'; import type { Logger } from '@kbn/logging'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import { createInitialState, type CreateInitialStateParams } from './initial_state'; import * as getOutdatedDocumentsQueryModule from './get_outdated_documents_query'; import { getOutdatedDocumentsQuery } from './get_outdated_documents_query'; @@ -64,6 +65,7 @@ describe('createInitialState', () => { typeRegistry, docLinks, logger, + esCapabilities: elasticsearchServiceMock.createCapabilities(), }; }); @@ -82,6 +84,9 @@ describe('createInitialState', () => { "currentAlias": ".kibana_task_manager", "discardCorruptObjects": false, "discardUnknownObjects": false, + "esCapabilities": Object { + "serverless": false, + }, "excludeFromUpgradeFilterHooks": Object {}, "excludeOnUpgradeQuery": Object { "bool": Object { diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.ts index eeb2065edb775..cf7494e655426 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.ts @@ -15,6 +15,7 @@ import type { IndexTypesMap, SavedObjectsMigrationConfigType, } from '@kbn/core-saved-objects-base-server-internal'; +import type { ElasticsearchCapabilities } from '@kbn/core-elasticsearch-server'; import { getOutdatedDocumentsQuery, type OutdatedDocumentsQueryParams, @@ -35,6 +36,7 @@ export interface CreateInitialStateParams extends OutdatedDocumentsQueryParams { typeRegistry: ISavedObjectTypeRegistry; docLinks: DocLinksServiceStart; logger: Logger; + esCapabilities: ElasticsearchCapabilities; } /** @@ -54,6 +56,7 @@ export const createInitialState = ({ typeRegistry, docLinks, logger, + esCapabilities, }: CreateInitialStateParams): InitState => { const outdatedDocumentsQuery = getOutdatedDocumentsQuery({ coreMigrationVersionPerType, @@ -137,5 +140,6 @@ export const createInitialState = ({ knownTypes, excludeFromUpgradeFilterHooks: excludeFilterHooks, migrationDocLinks, + esCapabilities, }; }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.test.ts index de210165578a5..bb60fd1c60c76 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.test.ts @@ -9,6 +9,7 @@ import { take } from 'rxjs/operators'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import type { SavedObjectsType } from '@kbn/core-saved-objects-server'; import { type MigrationResult, @@ -322,5 +323,6 @@ const mockOptions = (algorithm: 'v2' | 'zdt' = 'v2') => { client: mockedClient, docLinks: docLinksServiceMock.createSetupContract(), nodeRoles: { backgroundTasks: true, ui: true, migrator: true }, + esCapabilities: elasticsearchServiceMock.createCapabilities(), }; }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts index ac50e60027e2d..c06461da8fb43 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts @@ -15,7 +15,10 @@ import { BehaviorSubject } from 'rxjs'; import type { NodeRoles } from '@kbn/core-node-server'; import type { Logger } from '@kbn/logging'; import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ElasticsearchClient, + ElasticsearchCapabilities, +} from '@kbn/core-elasticsearch-server'; import { type SavedObjectUnsanitizedDoc, type ISavedObjectTypeRegistry, @@ -48,6 +51,7 @@ export interface KibanaMigratorOptions { docLinks: DocLinksServiceStart; waitForMigrationCompletion: boolean; nodeRoles: NodeRoles; + esCapabilities: ElasticsearchCapabilities; } /** @@ -71,6 +75,8 @@ export class KibanaMigrator implements IKibanaMigrator { private readonly docLinks: DocLinksServiceStart; private readonly waitForMigrationCompletion: boolean; private readonly nodeRoles: NodeRoles; + private readonly esCapabilities: ElasticsearchCapabilities; + public readonly kibanaVersion: string; /** @@ -87,6 +93,7 @@ export class KibanaMigrator implements IKibanaMigrator { docLinks, waitForMigrationCompletion, nodeRoles, + esCapabilities, }: KibanaMigratorOptions) { this.client = client; this.kibanaIndex = kibanaIndex; @@ -109,6 +116,7 @@ export class KibanaMigrator implements IKibanaMigrator { // operation so we cache the result this.activeMappings = buildActiveMappings(this.mappingProperties); this.docLinks = docLinks; + this.esCapabilities = esCapabilities; } public runMigrations({ rerun = false }: { rerun?: boolean } = {}): Promise { @@ -152,6 +160,7 @@ export class KibanaMigrator implements IKibanaMigrator { serializer: this.serializer, elasticsearchClient: this.client, nodeRoles: this.nodeRoles, + esCapabilities: this.esCapabilities, }); } else { return runV2Migration({ @@ -167,6 +176,7 @@ export class KibanaMigrator implements IKibanaMigrator { elasticsearchClient: this.client, mappingProperties: this.mappingProperties, waitForMigrationCompletion: this.waitForMigrationCompletion, + esCapabilities: this.esCapabilities, }); } } diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.test.ts index 77c1fb12b13ed..c8b630598f2e5 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/migrations_state_action_machine.test.ts @@ -15,6 +15,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as Option from 'fp-ts/lib/Option'; import { errors } from '@elastic/elasticsearch'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import type { AllControlStates, State } from './state'; import { createInitialState } from './initial_state'; import { ByteSizeValue } from '@kbn/config-schema'; @@ -63,6 +64,7 @@ describe('migrationsStateActionMachine', () => { }, typeRegistry, docLinks, + esCapabilities: elasticsearchServiceMock.createCapabilities(), logger: mockLogger.get(), }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts index 7039ce1cd1afa..29f7f95ba65db 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts @@ -9,6 +9,7 @@ import { chain } from 'lodash'; import * as Either from 'fp-ts/lib/Either'; import * as Option from 'fp-ts/lib/Option'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import type { SavedObjectsRawDoc } from '@kbn/core-saved-objects-server'; import { DEFAULT_INDEX_TYPES_MAP, @@ -125,6 +126,7 @@ describe('migrations v2 model', () => { waitForMigrationCompletion: false, mustRelocateDocuments: false, indexTypesMap: DEFAULT_INDEX_TYPES_MAP, + esCapabilities: elasticsearchServiceMock.createCapabilities(), }; const postInitState = { ...baseState, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts index b8d4afc55631d..0eedfc620a96e 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts @@ -137,6 +137,7 @@ export const nextActionMap = ( client, indexName: state.targetIndex, mappings: state.targetIndexMappings, + esCapabilities: state.esCapabilities, }), CREATE_REINDEX_TEMP: (state: CreateReindexTempState) => Actions.createIndex({ @@ -144,6 +145,7 @@ export const nextActionMap = ( indexName: state.tempIndex, aliases: [state.tempIndexAlias], mappings: state.tempIndexMappings, + esCapabilities: state.esCapabilities, }), READY_TO_REINDEX_SYNC: () => Actions.synchronizeMigrators({ @@ -194,7 +196,12 @@ export const nextActionMap = ( SET_TEMP_WRITE_BLOCK: (state: SetTempWriteBlock) => Actions.setWriteBlock({ client, index: state.tempIndex }), CLONE_TEMP_TO_TARGET: (state: CloneTempToTarget) => - Actions.cloneIndex({ client, source: state.tempIndex, target: state.targetIndex }), + Actions.cloneIndex({ + client, + source: state.tempIndex, + target: state.targetIndex, + esCapabilities: state.esCapabilities, + }), REFRESH_TARGET: (state: RefreshTarget) => Actions.refreshIndex({ client, index: state.targetIndex }), CHECK_TARGET_MAPPINGS: (state: CheckTargetMappingsState) => @@ -281,6 +288,7 @@ export const nextActionMap = ( client, indexName: state.sourceIndex.value, mappings: state.sourceIndexMappings.value, + esCapabilities: state.esCapabilities, }), LEGACY_REINDEX: (state: LegacyReindexState) => Actions.reindex({ diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_resilient_migrator.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_resilient_migrator.test.ts index bac468d06afe2..b6111b1f5f6ed 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_resilient_migrator.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_resilient_migrator.test.ts @@ -10,6 +10,7 @@ import buffer from 'buffer'; import { ByteSizeValue } from '@kbn/config-schema'; import { docLinksServiceMock } from '@kbn/core-doc-links-server-mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import type { MigrationResult } from '@kbn/core-saved-objects-base-server-internal'; import { createInitialState } from './initial_state'; @@ -79,6 +80,7 @@ describe('runResilientMigrator', () => { typeRegistry: options.typeRegistry, docLinks: options.docLinks, logger: options.logger, + esCapabilities: options.esCapabilities, }); // store the created initial state @@ -153,5 +155,6 @@ const mockOptions = (): RunResilientMigratorParams => { }, typeRegistry: savedObjectTypeRegistryMock, docLinks: docLinksServiceMock.createSetupContract(), + esCapabilities: elasticsearchServiceMock.createCapabilities(), }; }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_resilient_migrator.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_resilient_migrator.ts index 90bf2d2454fda..b799b3e179a7f 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_resilient_migrator.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_resilient_migrator.ts @@ -8,7 +8,10 @@ import type { Logger } from '@kbn/logging'; import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ElasticsearchClient, + ElasticsearchCapabilities, +} from '@kbn/core-elasticsearch-server'; import type { SavedObjectsMigrationVersion } from '@kbn/core-saved-objects-common'; import type { ISavedObjectTypeRegistry } from '@kbn/core-saved-objects-server'; import type { @@ -60,6 +63,7 @@ export interface RunResilientMigratorParams { migrationsConfig: SavedObjectsMigrationConfigType; typeRegistry: ISavedObjectTypeRegistry; docLinks: DocLinksServiceStart; + esCapabilities: ElasticsearchCapabilities; } /** @@ -86,6 +90,7 @@ export async function runResilientMigrator({ migrationsConfig, typeRegistry, docLinks, + esCapabilities, }: RunResilientMigratorParams): Promise { const initialState = createInitialState({ kibanaVersion, @@ -101,6 +106,7 @@ export async function runResilientMigrator({ typeRegistry, docLinks, logger, + esCapabilities, }); const migrationClient = client.child(MIGRATION_CLIENT_OPTIONS); return migrationStateActionMachine({ diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_v2_migration.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_v2_migration.test.ts index 3dc8b5cc782cb..3369071879e85 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_v2_migration.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_v2_migration.test.ts @@ -9,6 +9,7 @@ import buffer from 'buffer'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import { type MigrationResult, SavedObjectsSerializer, @@ -271,5 +272,6 @@ const mockOptions = (kibanaVersion = '8.2.3'): RunV2MigrationOpts => { }), serializer: new SavedObjectsSerializer(typeRegistry), mappingProperties: buildTypesMappings(typeRegistry.getAllTypes()), + esCapabilities: elasticsearchServiceMock.createCapabilities(), }; }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_v2_migration.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_v2_migration.ts index f39c74542a22d..ff79ebb2ec7fb 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_v2_migration.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/run_v2_migration.ts @@ -8,7 +8,10 @@ import type { Logger } from '@kbn/logging'; import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ElasticsearchClient, + ElasticsearchCapabilities, +} from '@kbn/core-elasticsearch-server'; import type { ISavedObjectTypeRegistry, ISavedObjectsSerializer, @@ -56,6 +59,8 @@ export interface RunV2MigrationOpts { mappingProperties: SavedObjectsTypeMappingDefinitions; /** Tells whether this instance should actively participate in the migration or not */ waitForMigrationCompletion: boolean; + /** Capabilities of the ES cluster we're using */ + esCapabilities: ElasticsearchCapabilities; } export const runV2Migration = async (options: RunV2MigrationOpts): Promise => { @@ -147,6 +152,7 @@ export const runV2Migration = async (options: RunV2MigrationOpts): Promise { return { migrationConfig, @@ -44,5 +45,6 @@ export const createContext = ({ batchSize: migrationConfig.batchSize, discardCorruptObjects: Boolean(migrationConfig.discardCorruptObjects), nodeRoles, + esCapabilities, }; }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/types.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/types.ts index 35edbb464ee17..3515d8a01a5a0 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/types.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/context/types.ts @@ -6,7 +6,10 @@ * Side Public License, v 1. */ -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ElasticsearchClient, + ElasticsearchCapabilities, +} from '@kbn/core-elasticsearch-server'; import type { NodeRoles } from '@kbn/core-node-server'; import type { ISavedObjectTypeRegistry, @@ -53,4 +56,6 @@ export interface MigratorContext { readonly discardCorruptObjects: boolean; /** The node roles of the Kibana instance */ readonly nodeRoles: NodeRoles; + /** Capabilities of the ES cluster we're using */ + readonly esCapabilities: ElasticsearchCapabilities; } diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migrate_index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migrate_index.ts index 33f094c765d3b..1ee07de5e0395 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migrate_index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/migrate_index.ts @@ -6,7 +6,10 @@ * Side Public License, v 1. */ -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ElasticsearchClient, + ElasticsearchCapabilities, +} from '@kbn/core-elasticsearch-server'; import { type SavedObjectsMigrationConfigType, type MigrationResult, @@ -45,6 +48,8 @@ export interface MigrateIndexOptions { elasticsearchClient: ElasticsearchClient; /** The node roles of the Kibana instance */ readonly nodeRoles: NodeRoles; + /** Capabilities of the ES cluster we're using */ + esCapabilities: ElasticsearchCapabilities; } export const migrateIndex = async ({ diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/next.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/next.ts index fe1093b0f4978..66df07ac37309 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/next.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/next.ts @@ -66,6 +66,7 @@ export const nextActionMap = (context: MigratorContext) => { client, indexName: state.currentIndex, mappings: state.indexMappings, + esCapabilities: context.esCapabilities, }), UPDATE_INDEX_MAPPINGS: (state: UpdateIndexMappingsState) => Actions.updateAndPickupMappings({ diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/run_zdt_migration.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/run_zdt_migration.ts index 8af4649711dbf..e8309f8d4d539 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/run_zdt_migration.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/run_zdt_migration.ts @@ -9,7 +9,10 @@ import type { Logger } from '@kbn/logging'; import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; import type { NodeRoles } from '@kbn/core-node-server'; -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ElasticsearchClient, + ElasticsearchCapabilities, +} from '@kbn/core-elasticsearch-server'; import type { ISavedObjectTypeRegistry, ISavedObjectsSerializer, @@ -43,6 +46,8 @@ export interface RunZeroDowntimeMigrationOpts { elasticsearchClient: ElasticsearchClient; /** The node roles of the Kibana instance */ nodeRoles: NodeRoles; + /** Capabilities of the ES cluster we're using */ + esCapabilities: ElasticsearchCapabilities; } export const runZeroDowntimeMigration = async ( diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/context.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/context.ts index ceb36a5aa7d42..cccef059f1c57 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/context.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/zdt/test_helpers/context.ts @@ -11,6 +11,7 @@ import { ElasticsearchClientMock, elasticsearchClientMock, } from '@kbn/core-elasticsearch-client-server-mocks'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import { SavedObjectTypeRegistry, type SavedObjectsMigrationConfigType, @@ -67,6 +68,7 @@ export const createContextMock = ( batchSize: 1000, discardCorruptObjects: false, nodeRoles: { migrator: true, ui: false, backgroundTasks: false }, + esCapabilities: elasticsearchServiceMock.createCapabilities(), ...parts, }; }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/tsconfig.json b/packages/core/saved-objects/core-saved-objects-migration-server-internal/tsconfig.json index 7a7583be64ab3..7bd1917e526b0 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/tsconfig.json +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/tsconfig.json @@ -32,6 +32,7 @@ "@kbn/core-saved-objects-base-server-mocks", "@kbn/core-elasticsearch-server-internal", "@kbn/core-node-server", + "@kbn/core-elasticsearch-server-mocks", ], "exclude": [ "target/**/*", diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/update.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/update.ts index 11a6545bfd612..b720260619aca 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/update.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/update.ts @@ -62,7 +62,12 @@ export const registerUpdateRoute = ( }); const { type, id } = req.params; const { attributes, version, references, upsert } = req.body; - const options: SavedObjectsUpdateOptions = { version, references, upsert }; + const options: SavedObjectsUpdateOptions = { + version, + references, + upsert, + migrationVersionCompatibility: 'raw' as const, + }; const usageStatsClient = coreUsageData.getClient(); usageStatsClient.incrementSavedObjectsUpdate({ request: req }).catch(() => {}); diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts index 860284a892fb1..0efda4a5bce9b 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts @@ -15,7 +15,10 @@ import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; import type { KibanaRequest } from '@kbn/core-http-server'; import type { InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { + ElasticsearchClient, + ElasticsearchCapabilities, +} from '@kbn/core-elasticsearch-server'; import type { InternalElasticsearchServiceSetup, InternalElasticsearchServiceStart, @@ -54,12 +57,13 @@ import { import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; import type { DeprecationRegistryProvider } from '@kbn/core-deprecations-server'; import type { NodeInfo } from '@kbn/core-node-server'; -import { MAIN_SAVED_OBJECT_INDEX, ALL_SAVED_OBJECT_INDICES } from '@kbn/core-saved-objects-server'; +import { MAIN_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; import { registerRoutes } from './routes'; import { calculateStatus$ } from './status'; import { registerCoreObjectTypes } from './object_types'; import { getSavedObjectsDeprecationsProvider } from './deprecations'; import { applyTypeDefaults } from './apply_type_defaults'; +import { getAllIndices } from './utils'; /** * @internal @@ -199,7 +203,6 @@ export class SavedObjectsService }, getTypeRegistry: () => this.typeRegistry, getDefaultIndex: () => MAIN_SAVED_OBJECT_INDEX, - getAllIndices: () => [...ALL_SAVED_OBJECT_INDICES], }; } @@ -223,7 +226,8 @@ export class SavedObjectsService elasticsearch.client.asInternalUser, docLinks, waitForMigrationCompletion, - node + node, + elasticsearch.getCapabilities() ); this.migrator$.next(migrator); @@ -322,6 +326,8 @@ export class SavedObjectsService clientProvider.setClientFactory(clientFactory); } + const allIndices = getAllIndices({ registry: this.typeRegistry }); + this.started = true; return { @@ -357,7 +363,7 @@ export class SavedObjectsService }); return [...indices]; }, - getAllIndices: () => [...ALL_SAVED_OBJECT_INDICES], + getAllIndices: () => [...allIndices], }; } @@ -368,7 +374,8 @@ export class SavedObjectsService client: ElasticsearchClient, docLinks: DocLinksServiceStart, waitForMigrationCompletion: boolean, - nodeInfo: NodeInfo + nodeInfo: NodeInfo, + esCapabilities: ElasticsearchCapabilities ): IKibanaMigrator { return new KibanaMigrator({ typeRegistry: this.typeRegistry, @@ -381,6 +388,7 @@ export class SavedObjectsService docLinks, waitForMigrationCompletion, nodeRoles: nodeInfo.roles, + esCapabilities, }); } } diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/get_all_indices.test.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/get_all_indices.test.ts new file mode 100644 index 0000000000000..c3a09df0ed529 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/get_all_indices.test.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 SavedObjectsType, MAIN_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; +import { SavedObjectTypeRegistry } from '@kbn/core-saved-objects-base-server-internal'; +import { getAllIndices } from './get_all_indices'; + +describe('getAllIndices', () => { + const createType = (parts: Partial): SavedObjectsType => ({ + name: 'test', + hidden: false, + namespaceType: 'single', + mappings: { properties: {} }, + ...parts, + }); + + const createRegistry = (...types: Array>): SavedObjectTypeRegistry => { + const registry = new SavedObjectTypeRegistry(); + types.forEach((type) => { + registry.registerType(createType(type)); + }); + + return registry; + }; + + it('returns the indices that are used by registered types', () => { + const registry = createRegistry( + { name: 'type_1' }, + { name: 'type_2', indexPattern: '.kibana_ingest' } + ); + expect(getAllIndices({ registry })).toEqual([MAIN_SAVED_OBJECT_INDEX, '.kibana_ingest']); + }); + + it('returns each index only once', () => { + const registry = createRegistry( + { name: 'type_1' }, + { name: 'type_2', indexPattern: '.kibana_foo' }, + { name: 'type_3' }, + { name: 'type_4', indexPattern: '.kibana_foo' } + ); + expect(getAllIndices({ registry })).toEqual([MAIN_SAVED_OBJECT_INDEX, '.kibana_foo']); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/get_all_indices.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/get_all_indices.ts new file mode 100644 index 0000000000000..166cbf8f78ef1 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/get_all_indices.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 and the Server Side Public License, v 1; you may 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 { MAIN_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; +import type { SavedObjectTypeRegistry } from '@kbn/core-saved-objects-base-server-internal'; + +export const getAllIndices = ({ registry }: { registry: SavedObjectTypeRegistry }): string[] => { + return [ + ...new Set(registry.getAllTypes().map((type) => type.indexPattern ?? MAIN_SAVED_OBJECT_INDEX)), + ]; +}; diff --git a/src/plugins/discover/public/components/index.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/index.ts similarity index 85% rename from src/plugins/discover/public/components/index.ts rename to packages/core/saved-objects/core-saved-objects-server-internal/src/utils/index.ts index a794b8c90a477..e931a9c64c039 100644 --- a/src/plugins/discover/public/components/index.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/index.ts @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export { DeferredSpinner } from './common/deferred_spinner'; +export { getAllIndices } from './get_all_indices'; diff --git a/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts b/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts index 2d7d5ff847330..58b7c424ac19a 100644 --- a/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts +++ b/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts @@ -77,11 +77,9 @@ const createSetupContractMock = () => { setSpacesExtension: jest.fn(), registerType: jest.fn(), getDefaultIndex: jest.fn(), - getAllIndices: jest.fn(), }; setupContract.getDefaultIndex.mockReturnValue(MAIN_SAVED_OBJECT_INDEX); - setupContract.getAllIndices.mockReturnValue([MAIN_SAVED_OBJECT_INDEX]); return setupContract; }; diff --git a/packages/core/saved-objects/core-saved-objects-server/src/contracts.ts b/packages/core/saved-objects/core-saved-objects-server/src/contracts.ts index e08da10172f3c..1f20524f9a114 100644 --- a/packages/core/saved-objects/core-saved-objects-server/src/contracts.ts +++ b/packages/core/saved-objects/core-saved-objects-server/src/contracts.ts @@ -137,13 +137,6 @@ export interface SavedObjectsServiceSetup { * Returns the default index used for saved objects. */ getDefaultIndex: () => string; - - /** - * Returns all (aliases to) kibana system indices used for saved object storage. - * - * @deprecated use the `start` contract counterpart. - */ - getAllIndices: () => string[]; } /** @@ -235,6 +228,8 @@ export interface SavedObjectsServiceStart { getDefaultIndex: () => string; /** * Returns all (aliases to) kibana system indices used for saved object storage. + * + * @remarks Only the indices effectively present in the current running environment will be returned. */ getAllIndices: () => string[]; } diff --git a/packages/core/saved-objects/core-saved-objects-server/src/serialization.ts b/packages/core/saved-objects/core-saved-objects-server/src/serialization.ts index 8b3b6b4924d79..a5fbf87145d8d 100644 --- a/packages/core/saved-objects/core-saved-objects-server/src/serialization.ts +++ b/packages/core/saved-objects/core-saved-objects-server/src/serialization.ts @@ -73,7 +73,12 @@ export interface SavedObjectsRawDoc { _primary_term?: number; } -/** @public */ +/** + * Saved object document as stored in `_source` of doc in ES index + * Similar to SavedObjectDoc and excludes `version`, includes `references`, has `attributes` in [typeMapping] + * + * @public + */ export interface SavedObjectsRawDocSource { type: string; namespace?: string; diff --git a/packages/core/saved-objects/docs/openapi/bundled.json b/packages/core/saved-objects/docs/openapi/bundled.json index 4cf712ff25fcb..d31407a937948 100644 --- a/packages/core/saved-objects/docs/openapi/bundled.json +++ b/packages/core/saved-objects/docs/openapi/bundled.json @@ -92,23 +92,741 @@ } } }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + }, + "429": { + "description": "Already in progress.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/_bulk_create": { + "post": { + "summary": "Create multiple Kibana saved objects.", + "operationId": "bulkCreateSavedObjects", + "deprecated": true, + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "in": "query", + "name": "overwrite", + "description": "When true, overwrites the document with the same identifier.", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/_bulk_delete": { + "post": { + "summary": "Remove multiple Kibana saved objects.", + "operationId": "bulkDeleteSavedObjects", + "description": "WARNING: When you delete a saved object, it cannot be recovered.\n", + "deprecated": true, + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "in": "query", + "name": "force", + "description": "When true, force delete objects that exist in multiple namespaces. Note that the option applies to the whole request. Use the delete object API to specify per-object deletion behavior. TIP: Use this if you attempted to delete objects and received an HTTP 400 error with the following message: \"Unable to delete saved object that exists in multiple namespaces, use the force option to delete it anyway\". WARNING: When you bulk delete objects that exist in multiple namespaces, the API also deletes legacy url aliases that reference the object. These requests are batched to minimise the impact but they can place a heavy load on Kibana. Make sure you limit the number of objects that exist in multiple namespaces in a single bulk delete operation.\n", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call. NOTE: This HTTP response code indicates that the bulk operation succeeded. Errors pertaining to individual objects will be returned in the response body.\n", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/_bulk_get": { + "post": { + "summary": "Retrieve multiple Kibana saved objects by identifier.", + "operationId": "bulkGetSavedObjects", + "deprecated": true, + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/_bulk_resolve": { + "post": { + "summary": "Retrieve multiple Kibana saved objects by identifier using any legacy URL aliases if they exist.", + "operationId": "bulkResolveSavedObjects", + "deprecated": true, + "description": "Under certain circumstances when Kibana is upgraded, saved object migrations may necessitate regenerating some object IDs to enable new features. When an object's ID is regenerated, a legacy URL alias is created for that object, preserving its old ID. In such a scenario, that object can be retrieved by the bulk resolve API using either its new ID or its old ID.\n", + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call. NOTE: This HTTP response code indicates that the bulk operation succeeded. Errors pertaining to individual objects will be returned in the response body. \n", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/_bulk_update": { + "post": { + "summary": "Update the attributes for multiple Kibana saved objects.", + "operationId": "bulkUpdateSavedObjects", + "deprecated": true, + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call. NOTE: This HTTP response code indicates that the bulk operation succeeded. Errors pertaining to individual objects will be returned in the response body. \n", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/_export": { + "post": { + "summary": "Retrieve sets of saved objects that you want to import into Kibana.", + "operationId": "exportSavedObjects", + "description": "\nYou must include `type` or `objects` in the request body.\n\nNOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be exported.\n\nThis functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "excludeExportDetails": { + "description": "Do not add export details entry at the end of the stream.", + "type": "boolean", + "default": false + }, + "includeReferencesDeep": { + "description": "Includes all of the referenced objects in the exported objects.", + "type": "boolean" + }, + "objects": { + "description": "A list of objects to export.", + "type": "array", + "items": { + "type": "object" + } + }, + "type": { + "description": "The saved object types to include in the export. Use `*` to export all the types.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + }, + "examples": { + "exportSavedObjectsRequest": { + "$ref": "#/components/examples/export_objects_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/x-ndjson": { + "schema": { + "type": "object", + "additionalProperties": true + }, + "examples": { + "exportSavedObjectsResponse": { + "$ref": "#/components/examples/export_objects_response" + } + } + } + } + }, "400": { "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/_find": { + "get": { + "summary": "Retrieve a paginated set of Kibana saved objects.", + "operationId": "findSavedObjects", + "deprecated": true, + "tags": [ + "saved objects" + ], + "parameters": [ + { + "in": "query", + "name": "aggs", + "description": "An aggregation structure, serialized as a string. The field format is similar to filter, meaning that to use a saved object type attribute in the aggregation, the `savedObjectType.attributes.title: \"myTitle\"` format must be used. For root fields, the syntax is `savedObjectType.rootField`. NOTE: As objects change in Kibana, the results on each page of the response also change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data.\n", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "default_search_operator", + "description": "The default operator to use for the `simple_query_string`.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "fields", + "description": "The fields to return in the attributes key of the response.", + "schema": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array" + } + ] + } + }, + { + "in": "query", + "name": "filter", + "description": "The filter is a KQL string with the caveat that if you filter with an attribute from your saved object type, it should look like that: `savedObjectType.attributes.title: \"myTitle\"`. However, if you use a root attribute of a saved object such as `updated_at`, you will have to define your filter like that: `savedObjectType.updated_at > 2018-12-22`.\n", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "has_no_reference", + "description": "Filters to objects that do not have a relationship with the type and identifier combination.", + "schema": { + "type": "object" + } + }, + { + "in": "query", + "name": "has_no_reference_operator", + "description": "The operator to use for the `has_no_reference` parameter. Either `OR` or `AND`. Defaults to `OR`.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "has_reference", + "description": "Filters to objects that have a relationship with the type and ID combination.", + "schema": { + "type": "object" + } + }, + { + "in": "query", + "name": "has_reference_operator", + "description": "The operator to use for the `has_reference` parameter. Either `OR` or `AND`. Defaults to `OR`.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "page", + "description": "The page of objects to return.", + "schema": { + "type": "integer" + } + }, + { + "in": "query", + "name": "per_page", + "description": "The number of objects to return per page.", + "schema": { + "type": "integer" + } + }, + { + "in": "query", + "name": "search", + "description": "An Elasticsearch `simple_query_string` query that filters the objects in the response.", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "search_fields", + "description": "The fields to perform the `simple_query_string` parsed query against.", + "schema": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array" + } + ] + } + }, + { + "in": "query", + "name": "sort_field", + "description": "Sorts the response. Includes \"root\" and \"type\" fields. \"root\" fields exist for all saved objects, such as \"updated_at\". \"type\" fields are specific to an object type, such as fields returned in the attributes key of the response. When a single type is defined in the type parameter, the \"root\" and \"type\" fields are allowed, and validity checks are made in that order. When multiple types are defined in the type parameter, only \"root\" fields are allowed.\n", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "type", + "description": "The saved object types to include.", + "required": true, + "schema": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array" + } + ] + } + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/_import": { + "post": { + "summary": "Create sets of Kibana saved objects from a file created by the export API.", + "operationId": "importSavedObjects", + "description": "Saved objects can be imported only into the same version, a newer minor on the same major, or the next major. Exported saved objects are not backwards compatible and cannot be imported into an older version of Kibana.\n\nThis functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "in": "query", + "name": "createNewCopies", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "Creates copies of saved objects, regenerates each object ID, and resets the origin. When used, potential conflict errors are avoided. NOTE: This option cannot be used with the `overwrite` and `compatibilityMode` options.\n" + }, + { + "in": "query", + "name": "overwrite", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "Overwrites saved objects when they already exist. When used, potential conflict errors are automatically resolved by overwriting the destination object. NOTE: This option cannot be used with the `createNewCopies` option.\n" + }, + { + "in": "query", + "name": "compatibilityMode", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "Applies various adjustments to the saved objects that are being imported to maintain compatibility between different Kibana versions. Use this option only if you encounter issues with imported saved objects. NOTE: This option cannot be used with the `createNewCopies` option.\n" + } + ], + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "description": "A file exported using the export API. NOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be included in this file. Similarly, the `savedObjects.maxImportPayloadBytes` setting limits the overall size of the file that can be imported.\n" + } + } + }, + "examples": { + "importObjectsRequest": { + "$ref": "#/components/examples/import_objects_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", "content": { "application/json": { "schema": { "type": "object", - "additionalProperties": true + "properties": { + "success": { + "type": "boolean", + "description": "Indicates when the import was successfully completed. When set to false, some objects may not have been created. For additional information, refer to the `errors` and `successResults` properties.\n" + }, + "successCount": { + "type": "integer", + "description": "Indicates the number of successfully imported records." + }, + "errors": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Indicates the import was unsuccessful and specifies the objects that failed to import.\n\nNOTE: One object may result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and conflict error.\n" + }, + "successResults": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Indicates the objects that are successfully imported, with any metadata if applicable.\n\nNOTE: Objects are created only when all resolvable errors are addressed, including conflicts and missing references. If objects are created as new copies, each entry in the `successResults` array includes a `destinationId` attribute.\n" + } + } + }, + "examples": { + "importObjectsResponse": { + "$ref": "#/components/examples/import_objects_response" + } } } } }, - "429": { - "description": "Already in progress.", + "400": { + "description": "Bad request.", "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/400_response" } } } @@ -126,61 +844,108 @@ } ] }, - "/api/saved_objects/_export": { + "/api/saved_objects/_resolve_import_errors": { "post": { - "summary": "Retrieve sets of saved objects that you want to import into Kibana.", - "operationId": "exportSavedObjects", - "description": "\nYou must include `type` or `objects` in the request body.\n\nNOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be exported.\n\nThis functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "summary": "Resolve errors from the Import objects API.", + "operationId": "resolveImportErrors", + "description": "To resolve errors, you can: \n\n* Retry certain saved objects\n* Overwrite specific saved objects\n* Change references to different saved objects\n\nThis functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "saved objects" ], "parameters": [ { "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "in": "query", + "name": "compatibilityMode", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "Applies various adjustments to the saved objects that are being imported to maintain compatibility between different Kibana versions. When enabled during the initial import, also enable when resolving import errors. This option cannot be used with the `createNewCopies` option.\n" + }, + { + "in": "query", + "name": "createNewCopies", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "Creates copies of the saved objects, regenerates each object ID, and resets the origin. When enabled during the initial import, also enable when resolving import errors.\n" } ], "requestBody": { "required": true, "content": { - "application/json": { + "multipart/form-data": { "schema": { "type": "object", + "required": [ + "retries" + ], "properties": { - "excludeExportDetails": { - "description": "Do not add export details entry at the end of the stream.", - "type": "boolean", - "default": false - }, - "includeReferencesDeep": { - "description": "Includes all of the referenced objects in the exported objects.", - "type": "boolean" + "file": { + "description": "The same file given to the import API.", + "type": "string", + "format": "binary" }, - "objects": { - "description": "A list of objects to export.", + "retries": { + "description": "The retry operations, which can specify how to resolve different types of errors.", "type": "array", "items": { - "type": "object" - } - }, - "type": { - "description": "The saved object types to include in the export. Use `*` to export all the types.", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "description": "The saved object type.", "type": "string" + }, + "id": { + "description": "The saved object ID.", + "type": "string" + }, + "overwrite": { + "description": "When set to `true`, the source object overwrites the conflicting destination object. When set to `false`, does nothing.", + "type": "boolean" + }, + "destinationId": { + "description": "Specifies the destination ID that the imported object should have, if different from the current ID.", + "type": "string" + }, + "replaceReferences": { + "description": "A list of `type`, `from`, and `to` used to change the object references.", + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "from": { + "type": "string" + }, + "to": { + "type": "string" + } + } + } + }, + "ignoreMissingReferences": { + "description": "When set to `true`, ignores missing reference errors. When set to `false`, does nothing.", + "type": "boolean" } } - ] + } } } }, "examples": { - "exportSavedObjectsRequest": { - "$ref": "#/components/examples/export_objects_request" + "resolveImportErrorsRequest": { + "$ref": "#/components/examples/resolve_missing_reference_request" } } } @@ -190,14 +955,37 @@ "200": { "description": "Indicates a successful call.", "content": { - "application/x-ndjson": { + "application/json": { "schema": { "type": "object", - "additionalProperties": true + "properties": { + "success": { + "type": "boolean", + "description": "Indicates a successful import. When set to `false`, some objects may not have been created. For additional information, refer to the `errors` and `successResults` properties.\n" + }, + "successCount": { + "type": "number", + "description": "Indicates the number of successfully resolved records.\n" + }, + "errors": { + "type": "array", + "description": "Specifies the objects that failed to resolve.\n\nNOTE: One object can result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and a `conflict` error.\n", + "items": { + "type": "object" + } + }, + "successResults": { + "type": "array", + "description": "Indicates the objects that are successfully imported, with any metadata if applicable.\n\nNOTE: Objects are only created when all resolvable errors are addressed, including conflict and missing references.\n", + "items": { + "type": "object" + } + } + } }, "examples": { - "exportSavedObjectsResponse": { - "$ref": "#/components/examples/export_objects_response" + "resolveImportErrorsResponse": { + "$ref": "#/components/examples/resolve_missing_reference_response" } } } @@ -208,8 +996,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": true + "$ref": "#/components/schemas/400_response" } } } @@ -227,11 +1014,11 @@ } ] }, - "/api/saved_objects/_import": { + "/api/saved_objects/{type}": { "post": { - "summary": "Create sets of Kibana saved objects from a file created by the export API.", - "operationId": "importSavedObjects", - "description": "Saved objects can be imported only into the same version, a newer minor on the same major, or the next major. Exported saved objects are not backwards compatible and cannot be imported into an older version of Kibana.\n\nThis functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "summary": "Create Kibana saved objects with randomly generated identifiers.", + "operationId": "createSavedObject", + "deprecated": true, "tags": [ "saved objects" ], @@ -239,50 +1026,161 @@ { "$ref": "#/components/parameters/kbn_xsrf" }, + { + "$ref": "#/components/parameters/saved_object_type" + }, { "in": "query", - "name": "createNewCopies", + "name": "overwrite", + "description": "If true, overwrites the document with the same identifier.", "schema": { "type": "boolean" - }, - "required": false, - "description": "Creates copies of saved objects, regenerates each object ID, and resets the origin. When used, potential conflict errors are avoided. NOTE: This option cannot be used with the `overwrite` and `compatibilityMode` options.\n" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "attributes" + ], + "properties": { + "attributes": { + "$ref": "#/components/schemas/attributes" + }, + "initialNamespaces": { + "$ref": "#/components/schemas/initial_namespaces" + }, + "references": { + "$ref": "#/components/schemas/references" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "409": { + "description": "Indicates a conflict error.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/{type}/{id}": { + "get": { + "summary": "Retrieve a single Kibana saved object by identifier.", + "operationId": "getSavedObject", + "deprecated": true, + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/saved_object_id" + }, + { + "$ref": "#/components/parameters/saved_object_type" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "post": { + "summary": "Create Kibana saved objects.", + "operationId": "createSavedObjectId", + "deprecated": true, + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/saved_object_id" }, { - "in": "query", - "name": "overwrite", - "schema": { - "type": "boolean" - }, - "required": false, - "description": "Overwrites saved objects when they already exist. When used, potential conflict errors are automatically resolved by overwriting the destination object. NOTE: This option cannot be used with the `createNewCopies` option.\n" + "$ref": "#/components/parameters/saved_object_type" }, { "in": "query", - "name": "compatibilityMode", + "name": "overwrite", + "description": "If true, overwrites the document with the same identifier.", "schema": { "type": "boolean" - }, - "required": false, - "description": "Applies various adjustments to the saved objects that are being imported to maintain compatibility between different Kibana versions. Use this option only if you encounter issues with imported saved objects. NOTE: This option cannot be used with the `createNewCopies` option.\n" + } } ], "requestBody": { "required": true, "content": { - "multipart/form-data": { + "application/json": { "schema": { "type": "object", + "required": [ + "attributes" + ], "properties": { - "file": { - "description": "A file exported using the export API. NOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be included in this file. Similarly, the `savedObjects.maxImportPayloadBytes` setting limits the overall size of the file that can be imported.\n" + "attributes": { + "$ref": "#/components/schemas/attributes" + }, + "initialNamespaces": { + "$ref": "#/components/schemas/initial_namespaces" + }, + "references": { + "$ref": "#/components/schemas/initial_namespaces" } } - }, - "examples": { - "importObjectsRequest": { - "$ref": "#/components/examples/import_objects_request" - } } } } @@ -293,69 +1191,27 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Indicates when the import was successfully completed. When set to false, some objects may not have been created. For additional information, refer to the `errors` and `successResults` properties.\n" - }, - "successCount": { - "type": "integer", - "description": "Indicates the number of successfully imported records." - }, - "errors": { - "type": "array", - "items": { - "type": "object" - }, - "description": "Indicates the import was unsuccessful and specifies the objects that failed to import.\n\nNOTE: One object may result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and conflict error.\n" - }, - "successResults": { - "type": "array", - "items": { - "type": "object" - }, - "description": "Indicates the objects that are successfully imported, with any metadata if applicable.\n\nNOTE: Objects are created only when all resolvable errors are addressed, including conflicts and missing references. If objects are created as new copies, each entry in the `successResults` array includes a `destinationId` attribute.\n" - } - } - }, - "examples": { - "importObjectsResponse": { - "$ref": "#/components/examples/import_objects_response" - } + "type": "object" } } } }, - "400": { - "description": "Bad request.", + "409": { + "description": "Indicates a conflict error.", "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": true + "type": "object" } } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] - }, - "/api/saved_objects/_resolve_import_errors": { - "post": { - "summary": "Resolve errors from the Import objects API.", - "operationId": "resolveImportErrors", - "description": "To resolve errors, you can: \n\n* Retry certain saved objects\n* Overwrite specific saved objects\n* Change references to different saved objects\n\nThis functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + }, + "put": { + "summary": "Update the attributes for Kibana saved objects.", + "operationId": "updateSavedObject", + "deprecated": true, "tags": [ "saved objects" ], @@ -364,136 +1220,85 @@ "$ref": "#/components/parameters/kbn_xsrf" }, { - "in": "query", - "name": "compatibilityMode", - "schema": { - "type": "boolean" - }, - "required": false, - "description": "Applies various adjustments to the saved objects that are being imported to maintain compatibility between different Kibana versions. When enabled during the initial import, also enable when resolving import errors. This option cannot be used with the `createNewCopies` option.\n" + "$ref": "#/components/parameters/saved_object_id" }, { - "in": "query", - "name": "createNewCopies", - "schema": { - "type": "boolean" - }, - "required": false, - "description": "Creates copies of the saved objects, regenerates each object ID, and resets the origin. When enabled during the initial import, also enable when resolving import errors.\n" + "$ref": "#/components/parameters/saved_object_type" } ], "requestBody": { "required": true, "content": { - "multipart/form-data": { + "application/json": { "schema": { - "type": "object", - "required": [ - "retries" - ], - "properties": { - "file": { - "description": "The same file given to the import API.", - "type": "string", - "format": "binary" - }, - "retries": { - "description": "The retry operations, which can specify how to resolve different types of errors.", - "type": "array", - "items": { - "type": "object", - "required": [ - "type", - "id" - ], - "properties": { - "type": { - "description": "The saved object type.", - "type": "string" - }, - "id": { - "description": "The saved object ID.", - "type": "string" - }, - "overwrite": { - "description": "When set to `true`, the source object overwrites the conflicting destination object. When set to `false`, does nothing.", - "type": "boolean" - }, - "destinationId": { - "description": "Specifies the destination ID that the imported object should have, if different from the current ID.", - "type": "string" - }, - "replaceReferences": { - "description": "A list of `type`, `from`, and `to` used to change the object references.", - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "from": { - "type": "string" - }, - "to": { - "type": "string" - } - } - } - }, - "ignoreMissingReferences": { - "description": "When set to `true`, ignores missing reference errors. When set to `false`, does nothing.", - "type": "boolean" - } - } - } - } + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object" } - }, - "examples": { - "resolveImportErrorsRequest": { - "$ref": "#/components/examples/resolve_missing_reference_request" + } + } + }, + "404": { + "description": "Indicates the object was not found.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "409": { + "description": "Indicates a conflict error.", + "content": { + "application/json": { + "schema": { + "type": "object" } } } } - }, + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/saved_objects/resolve/{type}/{id}": { + "get": { + "summary": "Retrieve a single Kibana saved object by identifier using any legacy URL alias if it exists.", + "operationId": "resolveSavedObject", + "description": "Under certain circumstances, when Kibana is upgraded, saved object migrations may necessitate regenerating some object IDs to enable new features. When an object's ID is regenerated, a legacy URL alias is created for that object, preserving its old ID. In such a scenario, that object can be retrieved using either its new ID or its old ID.\n", + "deprecated": true, + "tags": [ + "saved objects" + ], + "parameters": [ + { + "$ref": "#/components/parameters/saved_object_id" + }, + { + "$ref": "#/components/parameters/saved_object_type" + } + ], "responses": { "200": { "description": "Indicates a successful call.", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "description": "Indicates a successful import. When set to `false`, some objects may not have been created. For additional information, refer to the `errors` and `successResults` properties.\n" - }, - "successCount": { - "type": "number", - "description": "Indicates the number of successfully resolved records.\n" - }, - "errors": { - "type": "array", - "description": "Specifies the objects that failed to resolve.\n\nNOTE: One object can result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and a `conflict` error.\n", - "items": { - "type": "object" - } - }, - "successResults": { - "type": "array", - "description": "Indicates the objects that are successfully imported, with any metadata if applicable.\n\nNOTE: Objects are only created when all resolvable errors are addressed, including conflict and missing references.\n", - "items": { - "type": "object" - } - } - } - }, - "examples": { - "resolveImportErrorsResponse": { - "$ref": "#/components/examples/resolve_missing_reference_response" - } + "type": "object" } } } @@ -503,8 +1308,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": true + "$ref": "#/components/schemas/400_response" } } } @@ -680,6 +1484,46 @@ } } }, + "schemas": { + "400_response": { + "title": "Bad request", + "type": "object", + "required": [ + "error", + "message", + "statusCode" + ], + "properties": { + "error": { + "type": "string", + "enum": [ + "Bad Request" + ] + }, + "message": { + "type": "string" + }, + "statusCode": { + "type": "integer", + "enum": [ + 400 + ] + } + } + }, + "attributes": { + "type": "object", + "description": "The data that you want to create. WARNING: When you create saved objects, attributes are not validated, which allows you to pass arbitrary and ill-formed data into the API that can break Kibana. Make sure any data that you send to the API is properly formed.\n" + }, + "initial_namespaces": { + "type": "array", + "description": "Identifiers for the spaces in which this object is created. If this is provided, the object is created only in the explicitly defined spaces. If this is not provided, the object is created in the current space (default behavior). For shareable object types (registered with `namespaceType: 'multiple'`), this option can be used to specify one or more spaces, including the \"All spaces\" identifier ('*'). For isolated object types (registered with `namespaceType: 'single'` or `namespaceType: 'multiple-isolated'`), this option can only be used to specify a single space, and the \"All spaces\" identifier ('*') is not allowed. For global object types (`registered with `namespaceType: agnostic`), this option cannot be used.\n" + }, + "references": { + "type": "array", + "description": "Objects with `name`, `id`, and `type` properties that describe the other saved objects that this object references. Use `name` in attributes to refer to the other saved object, but never the `id`, which can update automatically during migrations or import and export.\n" + } + }, "parameters": { "kbn_xsrf": { "schema": { @@ -689,6 +1533,24 @@ "name": "kbn-xsrf", "description": "Cross-site request forgery protection", "required": true + }, + "saved_object_type": { + "in": "path", + "name": "type", + "description": "Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`.", + "required": true, + "schema": { + "type": "string" + } + }, + "saved_object_id": { + "in": "path", + "name": "id", + "description": "An identifier for the saved object.", + "required": true, + "schema": { + "type": "string" + } } } } diff --git a/packages/core/saved-objects/docs/openapi/bundled.yaml b/packages/core/saved-objects/docs/openapi/bundled.yaml index 92a91ba1d8f78..554895051768e 100644 --- a/packages/core/saved-objects/docs/openapi/bundled.yaml +++ b/packages/core/saved-objects/docs/openapi/bundled.yaml @@ -72,12 +72,11 @@ paths: rotateEncryptionKeyResponse: $ref: '#/components/examples/key_rotation_response' '400': - description: Bad request. + description: Bad request content: application/json: schema: - type: object - additionalProperties: true + $ref: '#/components/schemas/400_response' '429': description: Already in progress. content: @@ -88,6 +87,194 @@ paths: - url: https://localhost:5601 servers: - url: https://localhost:5601 + /api/saved_objects/_bulk_create: + post: + summary: Create multiple Kibana saved objects. + operationId: bulkCreateSavedObjects + deprecated: true + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - in: query + name: overwrite + description: When true, overwrites the document with the same identifier. + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/saved_objects/_bulk_delete: + post: + summary: Remove multiple Kibana saved objects. + operationId: bulkDeleteSavedObjects + description: | + WARNING: When you delete a saved object, it cannot be recovered. + deprecated: true + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - in: query + name: force + description: | + When true, force delete objects that exist in multiple namespaces. Note that the option applies to the whole request. Use the delete object API to specify per-object deletion behavior. TIP: Use this if you attempted to delete objects and received an HTTP 400 error with the following message: "Unable to delete saved object that exists in multiple namespaces, use the force option to delete it anyway". WARNING: When you bulk delete objects that exist in multiple namespaces, the API also deletes legacy url aliases that reference the object. These requests are batched to minimise the impact but they can place a heavy load on Kibana. Make sure you limit the number of objects that exist in multiple namespaces in a single bulk delete operation. + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: | + Indicates a successful call. NOTE: This HTTP response code indicates that the bulk operation succeeded. Errors pertaining to individual objects will be returned in the response body. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/saved_objects/_bulk_get: + post: + summary: Retrieve multiple Kibana saved objects by identifier. + operationId: bulkGetSavedObjects + deprecated: true + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/saved_objects/_bulk_resolve: + post: + summary: Retrieve multiple Kibana saved objects by identifier using any legacy URL aliases if they exist. + operationId: bulkResolveSavedObjects + deprecated: true + description: | + Under certain circumstances when Kibana is upgraded, saved object migrations may necessitate regenerating some object IDs to enable new features. When an object's ID is regenerated, a legacy URL alias is created for that object, preserving its old ID. In such a scenario, that object can be retrieved by the bulk resolve API using either its new ID or its old ID. + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: | + Indicates a successful call. NOTE: This HTTP response code indicates that the bulk operation succeeded. Errors pertaining to individual objects will be returned in the response body. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/saved_objects/_bulk_update: + post: + summary: Update the attributes for multiple Kibana saved objects. + operationId: bulkUpdateSavedObjects + deprecated: true + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: | + Indicates a successful call. NOTE: This HTTP response code indicates that the bulk operation succeeded. Errors pertaining to individual objects will be returned in the response body. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 /api/saved_objects/_export: post: summary: Retrieve sets of saved objects that you want to import into Kibana. @@ -145,11 +332,115 @@ paths: $ref: '#/components/examples/export_objects_response' '400': description: Bad request. + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/saved_objects/_find: + get: + summary: Retrieve a paginated set of Kibana saved objects. + operationId: findSavedObjects + deprecated: true + tags: + - saved objects + parameters: + - in: query + name: aggs + description: | + An aggregation structure, serialized as a string. The field format is similar to filter, meaning that to use a saved object type attribute in the aggregation, the `savedObjectType.attributes.title: "myTitle"` format must be used. For root fields, the syntax is `savedObjectType.rootField`. NOTE: As objects change in Kibana, the results on each page of the response also change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data. + schema: + type: string + - in: query + name: default_search_operator + description: The default operator to use for the `simple_query_string`. + schema: + type: string + - in: query + name: fields + description: The fields to return in the attributes key of the response. + schema: + oneOf: + - type: string + - type: array + - in: query + name: filter + description: | + The filter is a KQL string with the caveat that if you filter with an attribute from your saved object type, it should look like that: `savedObjectType.attributes.title: "myTitle"`. However, if you use a root attribute of a saved object such as `updated_at`, you will have to define your filter like that: `savedObjectType.updated_at > 2018-12-22`. + schema: + type: string + - in: query + name: has_no_reference + description: Filters to objects that do not have a relationship with the type and identifier combination. + schema: + type: object + - in: query + name: has_no_reference_operator + description: The operator to use for the `has_no_reference` parameter. Either `OR` or `AND`. Defaults to `OR`. + schema: + type: string + - in: query + name: has_reference + description: Filters to objects that have a relationship with the type and ID combination. + schema: + type: object + - in: query + name: has_reference_operator + description: The operator to use for the `has_reference` parameter. Either `OR` or `AND`. Defaults to `OR`. + schema: + type: string + - in: query + name: page + description: The page of objects to return. + schema: + type: integer + - in: query + name: per_page + description: The number of objects to return per page. + schema: + type: integer + - in: query + name: search + description: An Elasticsearch `simple_query_string` query that filters the objects in the response. + schema: + type: string + - in: query + name: search_fields + description: The fields to perform the `simple_query_string` parsed query against. + schema: + oneOf: + - type: string + - type: array + - in: query + name: sort_field + description: | + Sorts the response. Includes "root" and "type" fields. "root" fields exist for all saved objects, such as "updated_at". "type" fields are specific to an object type, such as fields returned in the attributes key of the response. When a single type is defined in the type parameter, the "root" and "type" fields are allowed, and validity checks are made in that order. When multiple types are defined in the type parameter, only "root" fields are allowed. + schema: + type: string + - in: query + name: type + description: The saved object types to include. + required: true + schema: + oneOf: + - type: string + - type: array + responses: + '200': + description: Indicates a successful call. content: application/json: schema: type: object - additionalProperties: true + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' servers: - url: https://localhost:5601 servers: @@ -239,8 +530,7 @@ paths: content: application/json: schema: - type: object - additionalProperties: true + $ref: '#/components/schemas/400_response' servers: - url: https://localhost:5601 servers: @@ -364,11 +654,189 @@ paths: $ref: '#/components/examples/resolve_missing_reference_response' '400': description: Bad request. + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/saved_objects/{type}: + post: + summary: Create Kibana saved objects with randomly generated identifiers. + operationId: createSavedObject + deprecated: true + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/saved_object_type' + - in: query + name: overwrite + description: If true, overwrites the document with the same identifier. + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - attributes + properties: + attributes: + $ref: '#/components/schemas/attributes' + initialNamespaces: + $ref: '#/components/schemas/initial_namespaces' + references: + $ref: '#/components/schemas/references' + responses: + '200': + description: Indicates a successful call. content: application/json: schema: type: object - additionalProperties: true + '409': + description: Indicates a conflict error. + content: + application/json: + schema: + type: object + servers: + - url: https://localhost:5601 + /api/saved_objects/{type}/{id}: + get: + summary: Retrieve a single Kibana saved object by identifier. + operationId: getSavedObject + deprecated: true + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/saved_object_id' + - $ref: '#/components/parameters/saved_object_type' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '400': + description: Bad request. + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + post: + summary: Create Kibana saved objects. + operationId: createSavedObjectId + deprecated: true + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/saved_object_id' + - $ref: '#/components/parameters/saved_object_type' + - in: query + name: overwrite + description: If true, overwrites the document with the same identifier. + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - attributes + properties: + attributes: + $ref: '#/components/schemas/attributes' + initialNamespaces: + $ref: '#/components/schemas/initial_namespaces' + references: + $ref: '#/components/schemas/initial_namespaces' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '409': + description: Indicates a conflict error. + content: + application/json: + schema: + type: object + put: + summary: Update the attributes for Kibana saved objects. + operationId: updateSavedObject + deprecated: true + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/saved_object_id' + - $ref: '#/components/parameters/saved_object_type' + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '404': + description: Indicates the object was not found. + content: + application/json: + schema: + type: object + '409': + description: Indicates a conflict error. + content: + application/json: + schema: + type: object + servers: + - url: https://localhost:5601 + /api/saved_objects/resolve/{type}/{id}: + get: + summary: Retrieve a single Kibana saved object by identifier using any legacy URL alias if it exists. + operationId: resolveSavedObject + description: | + Under certain circumstances, when Kibana is upgraded, saved object migrations may necessitate regenerating some object IDs to enable new features. When an object's ID is regenerated, a legacy URL alias is created for that object, preserving its old ID. In such a scenario, that object can be retrieved using either its new ID or its old ID. + deprecated: true + tags: + - saved objects + parameters: + - $ref: '#/components/parameters/saved_object_id' + - $ref: '#/components/parameters/saved_object_type' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '400': + description: Bad request. + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' servers: - url: https://localhost:5601 servers: @@ -478,6 +946,37 @@ components: meta: icon: dashboardApp title: Look at my dashboard + schemas: + 400_response: + title: Bad request + type: object + required: + - error + - message + - statusCode + properties: + error: + type: string + enum: + - Bad Request + message: + type: string + statusCode: + type: integer + enum: + - 400 + attributes: + type: object + description: | + The data that you want to create. WARNING: When you create saved objects, attributes are not validated, which allows you to pass arbitrary and ill-formed data into the API that can break Kibana. Make sure any data that you send to the API is properly formed. + initial_namespaces: + type: array + description: | + Identifiers for the spaces in which this object is created. If this is provided, the object is created only in the explicitly defined spaces. If this is not provided, the object is created in the current space (default behavior). For shareable object types (registered with `namespaceType: 'multiple'`), this option can be used to specify one or more spaces, including the "All spaces" identifier ('*'). For isolated object types (registered with `namespaceType: 'single'` or `namespaceType: 'multiple-isolated'`), this option can only be used to specify a single space, and the "All spaces" identifier ('*') is not allowed. For global object types (`registered with `namespaceType: agnostic`), this option cannot be used. + references: + type: array + description: | + Objects with `name`, `id`, and `type` properties that describe the other saved objects that this object references. Use `name` in attributes to refer to the other saved object, but never the `id`, which can update automatically during migrations or import and export. parameters: kbn_xsrf: schema: @@ -486,3 +985,17 @@ components: name: kbn-xsrf description: Cross-site request forgery protection required: true + saved_object_type: + in: path + name: type + description: Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`. + required: true + schema: + type: string + saved_object_id: + in: path + name: id + description: An identifier for the saved object. + required: true + schema: + type: string diff --git a/packages/core/saved-objects/docs/openapi/components/parameters/saved_object_id.yaml b/packages/core/saved-objects/docs/openapi/components/parameters/saved_object_id.yaml new file mode 100644 index 0000000000000..5cf3a824cc05e --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/parameters/saved_object_id.yaml @@ -0,0 +1,6 @@ +in: path +name: id +description: An identifier for the saved object. +required: true +schema: + type: string \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/components/parameters/saved_object_type.yaml b/packages/core/saved-objects/docs/openapi/components/parameters/saved_object_type.yaml new file mode 100644 index 0000000000000..9662a966f9d5f --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/parameters/saved_object_type.yaml @@ -0,0 +1,6 @@ +in: path +name: type +description: Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`. +required: true +schema: + type: string diff --git a/packages/core/saved-objects/docs/openapi/components/schemas/400_response.yaml b/packages/core/saved-objects/docs/openapi/components/schemas/400_response.yaml new file mode 100644 index 0000000000000..ab0887586c0eb --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/schemas/400_response.yaml @@ -0,0 +1,17 @@ +title: Bad request +type: object +required: + - error + - message + - statusCode +properties: + error: + type: string + enum: + - Bad Request + message: + type: string + statusCode: + type: integer + enum: + - 400 \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/components/schemas/attributes.yaml b/packages/core/saved-objects/docs/openapi/components/schemas/attributes.yaml new file mode 100644 index 0000000000000..61a107dcb21ad --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/schemas/attributes.yaml @@ -0,0 +1,4 @@ +type: object +description: > + The data that you want to create. + WARNING: When you create saved objects, attributes are not validated, which allows you to pass arbitrary and ill-formed data into the API that can break Kibana. Make sure any data that you send to the API is properly formed. \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/components/schemas/initial_namespaces.yaml b/packages/core/saved-objects/docs/openapi/components/schemas/initial_namespaces.yaml new file mode 100644 index 0000000000000..b7c2e94c97f33 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/schemas/initial_namespaces.yaml @@ -0,0 +1,8 @@ +type: array +description: > + Identifiers for the spaces in which this object is created. + If this is provided, the object is created only in the explicitly defined spaces. + If this is not provided, the object is created in the current space (default behavior). + For shareable object types (registered with `namespaceType: 'multiple'`), this option can be used to specify one or more spaces, including the "All spaces" identifier ('*'). + For isolated object types (registered with `namespaceType: 'single'` or `namespaceType: 'multiple-isolated'`), this option can only be used to specify a single space, and the "All spaces" identifier ('*') is not allowed. + For global object types (`registered with `namespaceType: agnostic`), this option cannot be used. \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/components/schemas/references.yaml b/packages/core/saved-objects/docs/openapi/components/schemas/references.yaml new file mode 100644 index 0000000000000..d734d081695da --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/schemas/references.yaml @@ -0,0 +1,4 @@ +type: array +description: > + Objects with `name`, `id`, and `type` properties that describe the other saved objects that this object references. + Use `name` in attributes to refer to the other saved object, but never the `id`, which can update automatically during migrations or import and export. \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/entrypoint.yaml b/packages/core/saved-objects/docs/openapi/entrypoint.yaml index 5da4c7cbb5cae..f20b8204b4bd4 100644 --- a/packages/core/saved-objects/docs/openapi/entrypoint.yaml +++ b/packages/core/saved-objects/docs/openapi/entrypoint.yaml @@ -18,30 +18,30 @@ paths: # Paths in the default space '/api/encrypted_saved_objects/_rotate_key': $ref: 'paths/api@encrypted_saved_objects@_rotate_key.yaml' -# '/api/saved_objects/_bulk_create': -# $ref: 'paths/api@saved_objects@_bulk_create.yaml' -# '/api/saved_objects/_bulk_delete': -# $ref: 'paths/api@saved_objects@_bulk_delete.yaml' -# '/api/saved_objects/_bulk_get': -# $ref: 'paths/api@saved_objects@_bulk_get.yaml' -# '/api/saved_objects/_bulk_resolve': -# $ref: 'paths/api@saved_objects@_bulk_resolve.yaml' -# '/api/saved_objects/_bulk_update': -# $ref: 'paths/api@saved_objects@_bulk_update.yaml' + '/api/saved_objects/_bulk_create': + $ref: 'paths/api@saved_objects@_bulk_create.yaml' + '/api/saved_objects/_bulk_delete': + $ref: 'paths/api@saved_objects@_bulk_delete.yaml' + '/api/saved_objects/_bulk_get': + $ref: 'paths/api@saved_objects@_bulk_get.yaml' + '/api/saved_objects/_bulk_resolve': + $ref: 'paths/api@saved_objects@_bulk_resolve.yaml' + '/api/saved_objects/_bulk_update': + $ref: 'paths/api@saved_objects@_bulk_update.yaml' '/api/saved_objects/_export': $ref: 'paths/api@saved_objects@_export.yaml' -# '/api/saved_objects/_find': -# $ref: 'paths/api@saved_objects@_find.yaml' + '/api/saved_objects/_find': + $ref: 'paths/api@saved_objects@_find.yaml' '/api/saved_objects/_import': $ref: 'paths/api@saved_objects@_import.yaml' '/api/saved_objects/_resolve_import_errors': $ref: 'paths/api@saved_objects@_resolve_import_errors.yaml' -# '/api/saved_objects/{type}': -# $ref: 'paths/api@saved_objects@{type}.yaml' -# '/api/saved_objects/{type}/{id}': -# $ref: 'paths/api@saved_objects@{type}@{id}.yaml -# 'api/saved_objects/resolve/{type}/{id}': -# $ref: 'paths/api@saved_objects@resolve@{type}@{id}.yaml' + '/api/saved_objects/{type}': + $ref: 'paths/api@saved_objects@{type}.yaml' + '/api/saved_objects/{type}/{id}': + $ref: 'paths/api@saved_objects@{type}@{id}.yaml' + '/api/saved_objects/resolve/{type}/{id}': + $ref: 'paths/api@saved_objects@resolve@{type}@{id}.yaml' components: securitySchemes: basicAuth: diff --git a/packages/core/saved-objects/docs/openapi/paths/api@encrypted_saved_objects@_rotate_key.yaml b/packages/core/saved-objects/docs/openapi/paths/api@encrypted_saved_objects@_rotate_key.yaml index 495d75bbb364a..94ab9cb3f6286 100644 --- a/packages/core/saved-objects/docs/openapi/paths/api@encrypted_saved_objects@_rotate_key.yaml +++ b/packages/core/saved-objects/docs/openapi/paths/api@encrypted_saved_objects@_rotate_key.yaml @@ -51,12 +51,11 @@ post: rotateEncryptionKeyResponse: $ref: '../components/examples/key_rotation_response.yaml' '400': - description: Bad request. - content: - application/json: - schema: - type: object - additionalProperties: true + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' '429': description: Already in progress. content: diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_create.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_create.yaml new file mode 100644 index 0000000000000..0461a1a618a75 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_create.yaml @@ -0,0 +1,39 @@ +post: + summary: Create multiple Kibana saved objects. + operationId: bulkCreateSavedObjects + deprecated: true + tags: + - saved objects + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - in: query + name: overwrite + description: When true, overwrites the document with the same identifier. + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_delete.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_delete.yaml new file mode 100644 index 0000000000000..c15fdde82b2a4 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_delete.yaml @@ -0,0 +1,48 @@ +post: + summary: Remove multiple Kibana saved objects. + operationId: bulkDeleteSavedObjects + description: > + WARNING: When you delete a saved object, it cannot be recovered. + deprecated: true + tags: + - saved objects + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - in: query + name: force + description: > + When true, force delete objects that exist in multiple namespaces. + Note that the option applies to the whole request. + Use the delete object API to specify per-object deletion behavior. + TIP: Use this if you attempted to delete objects and received an HTTP 400 error with the following message: "Unable to delete saved object that exists in multiple namespaces, use the force option to delete it anyway". + WARNING: When you bulk delete objects that exist in multiple namespaces, the API also deletes legacy url aliases that reference the object. These requests are batched to minimise the impact but they can place a heavy load on Kibana. Make sure you limit the number of objects that exist in multiple namespaces in a single bulk delete operation. + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: > + Indicates a successful call. + NOTE: This HTTP response code indicates that the bulk operation succeeded. + Errors pertaining to individual objects will be returned in the response body. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_get.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_get.yaml new file mode 100644 index 0000000000000..8512f5a04ef7f --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_get.yaml @@ -0,0 +1,33 @@ +post: + summary: Retrieve multiple Kibana saved objects by identifier. + operationId: bulkGetSavedObjects + deprecated: true + tags: + - saved objects + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_resolve.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_resolve.yaml new file mode 100644 index 0000000000000..9227bb782bfac --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_resolve.yaml @@ -0,0 +1,40 @@ +post: + summary: Retrieve multiple Kibana saved objects by identifier using any legacy URL aliases if they exist. + operationId: bulkResolveSavedObjects + deprecated: true + description: > + Under certain circumstances when Kibana is upgraded, saved object migrations may necessitate regenerating some object IDs to enable new features. + When an object's ID is regenerated, a legacy URL alias is created for that object, preserving its old ID. + In such a scenario, that object can be retrieved by the bulk resolve API using either its new ID or its old ID. + tags: + - saved objects + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: > + Indicates a successful call. + NOTE: This HTTP response code indicates that the bulk operation succeeded. + Errors pertaining to individual objects will be returned in the response body. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_update.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_update.yaml new file mode 100644 index 0000000000000..aa5e9e1f33c35 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_bulk_update.yaml @@ -0,0 +1,36 @@ +post: + summary: Update the attributes for multiple Kibana saved objects. + operationId: bulkUpdateSavedObjects + deprecated: true + tags: + - saved objects + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + responses: + '200': + description: > + Indicates a successful call. + NOTE: This HTTP response code indicates that the bulk operation succeeded. + Errors pertaining to individual objects will be returned in the response body. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_export.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_export.yaml index 717d4623a9346..931746d21ddc1 100644 --- a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_export.yaml +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_export.yaml @@ -57,8 +57,7 @@ post: content: application/json: schema: - type: object - additionalProperties: true + $ref: '../components/schemas/400_response.yaml' servers: - url: https://localhost:5601 servers: diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_find.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_find.yaml new file mode 100644 index 0000000000000..180a16534f8a0 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_find.yaml @@ -0,0 +1,111 @@ +get: + summary: Retrieve a paginated set of Kibana saved objects. + operationId: findSavedObjects + deprecated: true + tags: + - saved objects + parameters: + - in: query + name: aggs + description: > + An aggregation structure, serialized as a string. The field format is similar to filter, meaning that to use a saved object type attribute in the aggregation, the `savedObjectType.attributes.title: "myTitle"` format must be used. For root fields, the syntax is `savedObjectType.rootField`. + NOTE: As objects change in Kibana, the results on each page of the response also change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data. + schema: + type: string + - in: query + name: default_search_operator + description: The default operator to use for the `simple_query_string`. + schema: + type: string + - in: query + name: fields + description: The fields to return in the attributes key of the response. + schema: + oneOf: + - type: string + - type: array + - in: query + name: filter + description: > + The filter is a KQL string with the caveat that if you filter with an attribute from your saved object type, it should look like that: `savedObjectType.attributes.title: "myTitle"`. + However, if you use a root attribute of a saved object such as `updated_at`, you will have to define your filter like that: `savedObjectType.updated_at > 2018-12-22`. + schema: + type: string + - in: query + name: has_no_reference + description: Filters to objects that do not have a relationship with the type and identifier combination. + schema: + type: object + - in: query + name: has_no_reference_operator + description: The operator to use for the `has_no_reference` parameter. Either `OR` or `AND`. Defaults to `OR`. + schema: + type: string + - in: query + name: has_reference + description: Filters to objects that have a relationship with the type and ID combination. + schema: + type: object + - in: query + name: has_reference_operator + description: The operator to use for the `has_reference` parameter. Either `OR` or `AND`. Defaults to `OR`. + schema: + type: string + - in: query + name: page + description: The page of objects to return. + schema: + type: integer + - in: query + name: per_page + description: The number of objects to return per page. + schema: + type: integer + - in: query + name: search + description: An Elasticsearch `simple_query_string` query that filters the objects in the response. + schema: + type: string + - in: query + name: search_fields + description: The fields to perform the `simple_query_string` parsed query against. + schema: + oneOf: + - type: string + - type: array + - in: query + name: sort_field + description: > + Sorts the response. + Includes "root" and "type" fields. + "root" fields exist for all saved objects, such as "updated_at". + "type" fields are specific to an object type, such as fields returned in the attributes key of the response. + When a single type is defined in the type parameter, the "root" and "type" fields are allowed, and validity checks are made in that order. + When multiple types are defined in the type parameter, only "root" fields are allowed. + schema: + type: string + - in: query + name: type + description: The saved object types to include. + required: true + schema: + oneOf: + - type: string + - type: array + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_import.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_import.yaml index 2d7a8a7f5e554..5c538a2d1442f 100644 --- a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_import.yaml +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_import.yaml @@ -82,8 +82,7 @@ post: content: application/json: schema: - type: object - additionalProperties: true + $ref: '../components/schemas/400_response.yaml' servers: - url: https://localhost:5601 servers: diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_resolve_import_errors.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_resolve_import_errors.yaml index 66b3c38d2aee5..6c49f1925e3e5 100644 --- a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_resolve_import_errors.yaml +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_resolve_import_errors.yaml @@ -119,8 +119,7 @@ post: content: application/json: schema: - type: object - additionalProperties: true + $ref: '../components/schemas/400_response.yaml' servers: - url: https://localhost:5601 servers: diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@resolve@{type}@{id}.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@resolve@{type}@{id}.yaml new file mode 100644 index 0000000000000..bb1bd0d68bcef --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@resolve@{type}@{id}.yaml @@ -0,0 +1,31 @@ +get: + summary: Retrieve a single Kibana saved object by identifier using any legacy URL alias if it exists. + operationId: resolveSavedObject + description: > + Under certain circumstances, when Kibana is upgraded, saved object migrations may necessitate regenerating some object IDs to enable new features. + When an object's ID is regenerated, a legacy URL alias is created for that object, preserving its old ID. + In such a scenario, that object can be retrieved using either its new ID or its old ID. + deprecated: true + tags: + - saved objects + parameters: + - $ref: '../components/parameters/saved_object_id.yaml' + - $ref: '../components/parameters/saved_object_type.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '400': + description: Bad request. + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 + +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@{type}.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@{type}.yaml new file mode 100644 index 0000000000000..2005e4241b41f --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@{type}.yaml @@ -0,0 +1,44 @@ +post: + summary: Create Kibana saved objects with randomly generated identifiers. + operationId: createSavedObject + deprecated: true + tags: + - saved objects + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/saved_object_type.yaml' + - in: query + name: overwrite + description: If true, overwrites the document with the same identifier. + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - attributes + properties: + attributes: + $ref: '../components/schemas/attributes.yaml' + initialNamespaces: + $ref: '../components/schemas/initial_namespaces.yaml' + references: + $ref: '../components/schemas/references.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '409': + description: Indicates a conflict error. + content: + application/json: + schema: + type: object +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@{type}@{id}.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@{type}@{id}.yaml new file mode 100644 index 0000000000000..b92631817eba4 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@{type}@{id}.yaml @@ -0,0 +1,106 @@ +get: + summary: Retrieve a single Kibana saved object by identifier. + operationId: getSavedObject + deprecated: true + tags: + - saved objects + parameters: + - $ref: '../components/parameters/saved_object_id.yaml' + - $ref: '../components/parameters/saved_object_type.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '400': + description: Bad request. + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 + +post: + summary: Create Kibana saved objects. + operationId: createSavedObjectId + deprecated: true + tags: + - saved objects + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/saved_object_id.yaml' + - $ref: '../components/parameters/saved_object_type.yaml' + - in: query + name: overwrite + description: If true, overwrites the document with the same identifier. + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - attributes + properties: + attributes: + $ref: '../components/schemas/attributes.yaml' + initialNamespaces: + $ref: '../components/schemas/initial_namespaces.yaml' + references: + $ref: '../components/schemas/initial_namespaces.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '409': + description: Indicates a conflict error. + content: + application/json: + schema: + type: object + +put: + summary: Update the attributes for Kibana saved objects. + operationId: updateSavedObject + deprecated: true + tags: + - saved objects + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/saved_object_id.yaml' + - $ref: '../components/parameters/saved_object_type.yaml' + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + '404': + description: Indicates the object was not found. + content: + application/json: + schema: + type: object + '409': + description: Indicates a conflict error. + content: + application/json: + schema: + type: object +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts b/packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts index 0ff24ed58af09..3e12b16832714 100644 --- a/packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts +++ b/packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts @@ -5,17 +5,21 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ + +import Path from 'path'; import { defaultsDeep } from 'lodash'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; import { Cluster } from '@kbn/es'; -import Path from 'path'; import { REPO_ROOT } from '@kbn/repo-info'; import { ToolingLog } from '@kbn/tooling-log'; -import execa from 'execa'; import { CliArgs } from '@kbn/config'; import { createRoot, type TestElasticsearchUtils, type TestKibanaUtils } from './create_root'; -export type TestServerlessESUtils = Pick; +export type TestServerlessESUtils = Pick & { + getClient: () => Client; +}; export type TestServerlessKibanaUtils = TestKibanaUtils; + export interface TestServerlessUtils { startES: () => Promise; startKibana: (abortSignal?: AbortSignal) => Promise; @@ -37,9 +41,10 @@ export function createTestServerlessInstances({ adjustTimeout?.(120_000); return { startES: async () => { - const { stop } = await esUtils.start(); + const { stop, getClient } = await esUtils.start(); return { es: esUtils.es, + getClient, stop, }; }, @@ -58,6 +63,7 @@ export function createTestServerlessInstances({ }; } +const ES_BASE_PATH_DIR = Path.join(REPO_ROOT, '.es/es_test_serverless'); function createServerlessES() { const log = new ToolingLog({ level: 'info', @@ -68,33 +74,69 @@ function createServerlessES() { es, start: async () => { await es.runServerless({ - basePath: Path.join(REPO_ROOT, '.es/es_test_serverless'), + basePath: ES_BASE_PATH_DIR, + teardown: true, + background: true, + clean: true, + kill: true, + waitForReady: true, }); return { + getClient: getServerlessESClient, stop: async () => { - // hack to stop the ES cluster - await execa('docker', ['container', 'stop', 'es01', 'es02', 'es03']); + await es.stop(); }, }; }, }; } -const defaults = { - server: { - restrictInternalApis: true, - versioned: { - versionResolution: 'newest', - strictClientVersionCheck: false, +const getServerlessESClient = () => { + return new Client({ + // node ports not configurable from + node: 'http://localhost:9200', + Connection: HttpConnection, + }); +}; + +const getServerlessDefault = () => { + return { + server: { + restrictInternalApis: true, + versioned: { + versionResolution: 'newest', + strictClientVersionCheck: false, + }, + }, + migrations: { + algorithm: 'zdt', + zdt: { + runOnRoles: ['ui'], + }, }, - }, - migrations: { - algorithm: 'zdt', - }, - elasticsearch: { - serviceAccountToken: 'BEEF', - }, + logging: { + loggers: [ + { + name: 'root', + level: 'error', + appenders: ['console'], + }, + { + name: 'elasticsearch.deprecation', + level: 'all', + appenders: ['deprecation'], + }, + ], + appenders: { + deprecation: { type: 'console', layout: { type: 'json' } }, + console: { type: 'console', layout: { type: 'pattern' } }, + }, + }, + }; }; function createServerlessKibana(settings = {}, cliArgs: Partial = {}) { - return createRoot(defaultsDeep(settings, defaults), { ...cliArgs, serverless: true }); + return createRoot(defaultsDeep(settings, getServerlessDefault()), { + ...cliArgs, + serverless: true, + }); } diff --git a/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts b/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts index 279d5c68cd733..8e77ec7a0800c 100644 --- a/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts +++ b/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts @@ -101,6 +101,8 @@ export interface CoreUsageStats { 'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.no'?: number; 'apiCalls.savedObjectsImport.createNewCopiesEnabled.yes'?: number; 'apiCalls.savedObjectsImport.createNewCopiesEnabled.no'?: number; + 'apiCalls.savedObjectsImport.compatibilityModeEnabled.yes'?: number; + 'apiCalls.savedObjectsImport.compatibilityModeEnabled.no'?: number; 'apiCalls.savedObjectsImport.overwriteEnabled.yes'?: number; 'apiCalls.savedObjectsImport.overwriteEnabled.no'?: number; 'apiCalls.savedObjectsResolveImportErrors.total'?: number; diff --git a/packages/deeplinks/observability/constants.ts b/packages/deeplinks/observability/constants.ts index addd326de2ce3..a28c9e4aaff21 100644 --- a/packages/deeplinks/observability/constants.ts +++ b/packages/deeplinks/observability/constants.ts @@ -8,6 +8,8 @@ export const LOGS_APP_ID = 'logs'; +export const OBSERVABILITY_LOG_EXPLORER = 'observability-log-explorer'; + export const OBSERVABILITY_OVERVIEW_APP_ID = 'observability-overview'; export const METRICS_APP_ID = 'metrics'; diff --git a/packages/deeplinks/observability/deep_links.ts b/packages/deeplinks/observability/deep_links.ts index 19432ef37d3ba..1d405c1a20620 100644 --- a/packages/deeplinks/observability/deep_links.ts +++ b/packages/deeplinks/observability/deep_links.ts @@ -5,10 +5,10 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { DISCOVER_APP_ID } from '@kbn/deeplinks-analytics'; import { LOGS_APP_ID, + OBSERVABILITY_LOG_EXPLORER, OBSERVABILITY_OVERVIEW_APP_ID, METRICS_APP_ID, APM_APP_ID, @@ -16,6 +16,7 @@ import { } from './constants'; type LogsApp = typeof LOGS_APP_ID; +type ObservabilityLogExplorerApp = typeof OBSERVABILITY_LOG_EXPLORER; type ObservabilityOverviewApp = typeof OBSERVABILITY_OVERVIEW_APP_ID; type MetricsApp = typeof METRICS_APP_ID; type ApmApp = typeof APM_APP_ID; @@ -23,13 +24,12 @@ type ObservabilityOnboardingApp = typeof OBSERVABILITY_ONBOARDING_APP_ID; export type AppId = | LogsApp + | ObservabilityLogExplorerApp | ObservabilityOverviewApp | ObservabilityOnboardingApp | ApmApp | MetricsApp; -export type DiscoverLogExplorerId = `${typeof DISCOVER_APP_ID}:log-explorer`; - export type LogsLinkId = 'log-categories' | 'settings' | 'anomalies' | 'stream'; export type ObservabilityOverviewLinkId = @@ -55,7 +55,6 @@ export type LinkId = LogsLinkId | ObservabilityOverviewLinkId | MetricsLinkId | export type DeepLinkId = | AppId - | DiscoverLogExplorerId | `${LogsApp}:${LogsLinkId}` | `${ObservabilityOverviewApp}:${ObservabilityOverviewLinkId}` | `${MetricsApp}:${MetricsLinkId}` diff --git a/packages/deeplinks/observability/tsconfig.json b/packages/deeplinks/observability/tsconfig.json index 9f5bc24d4f316..94b099694eaf4 100644 --- a/packages/deeplinks/observability/tsconfig.json +++ b/packages/deeplinks/observability/tsconfig.json @@ -16,6 +16,5 @@ "target/**/*" ], "kbn_references": [ - "@kbn/deeplinks-analytics", ] } diff --git a/packages/deeplinks/search/constants.ts b/packages/deeplinks/search/constants.ts index db741ca76c094..75e23971bcbc7 100644 --- a/packages/deeplinks/search/constants.ts +++ b/packages/deeplinks/search/constants.ts @@ -7,5 +7,4 @@ */ export const SERVERLESS_ES_APP_ID = 'serverlessElasticsearch'; -export const SERVERLESS_ES_INDEXING_API_ID = 'serverlessIndexingApi'; export const SERVERLESS_ES_CONNECTORS_ID = 'serverlessConnectors'; diff --git a/packages/deeplinks/search/deep_links.ts b/packages/deeplinks/search/deep_links.ts index ec8f501eee4e2..420f308945ca3 100644 --- a/packages/deeplinks/search/deep_links.ts +++ b/packages/deeplinks/search/deep_links.ts @@ -6,14 +6,9 @@ * Side Public License, v 1. */ -import { - SERVERLESS_ES_APP_ID, - SERVERLESS_ES_CONNECTORS_ID, - SERVERLESS_ES_INDEXING_API_ID, -} from './constants'; +import { SERVERLESS_ES_APP_ID, SERVERLESS_ES_CONNECTORS_ID } from './constants'; export type AppId = typeof SERVERLESS_ES_APP_ID; -export type IndexingApiId = typeof SERVERLESS_ES_INDEXING_API_ID; export type ConnectorsId = typeof SERVERLESS_ES_CONNECTORS_ID; -export type DeepLinkId = AppId | IndexingApiId | ConnectorsId; +export type DeepLinkId = AppId | ConnectorsId; diff --git a/packages/deeplinks/search/index.ts b/packages/deeplinks/search/index.ts index a21db35a8627b..33c795a34382f 100644 --- a/packages/deeplinks/search/index.ts +++ b/packages/deeplinks/search/index.ts @@ -6,6 +6,6 @@ * Side Public License, v 1. */ -export { SERVERLESS_ES_APP_ID, SERVERLESS_ES_INDEXING_API_ID } from './constants'; +export { SERVERLESS_ES_APP_ID, SERVERLESS_ES_CONNECTORS_ID } from './constants'; export type { AppId, DeepLinkId } from './deep_links'; diff --git a/packages/kbn-alerts-as-data-utils/index.ts b/packages/kbn-alerts-as-data-utils/index.ts index 1194f863e2d85..81562c54b9e88 100644 --- a/packages/kbn-alerts-as-data-utils/index.ts +++ b/packages/kbn-alerts-as-data-utils/index.ts @@ -8,3 +8,4 @@ export * from './src/field_maps'; export * from './src/schemas'; +export * from './src/search'; diff --git a/packages/kbn-alerts-as-data-utils/jest.config.js b/packages/kbn-alerts-as-data-utils/jest.config.js new file mode 100644 index 0000000000000..347db52d6e768 --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/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-alerts-as-data-utils'], +}; diff --git a/packages/kbn-alerts-as-data-utils/src/search/index.ts b/packages/kbn-alerts-as-data-utils/src/search/index.ts new file mode 100644 index 0000000000000..b522c3c3dbf0d --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/search/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 { buildAlertFieldsRequest, ALERT_EVENTS_FIELDS } from './security'; diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/build_fields_request.test.ts b/packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.test.ts similarity index 51% rename from x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/build_fields_request.test.ts rename to packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.test.ts index b321516cde1a8..617d28b1acdcb 100644 --- a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/build_fields_request.test.ts +++ b/packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.test.ts @@ -1,34 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { buildFieldsRequest } from './build_fields_request'; -import { TIMELINE_EVENTS_FIELDS } from './constants'; + +import { buildAlertFieldsRequest } from './build_fields_request'; +import { ALERT_EVENTS_FIELDS } from './fields'; describe('buildFieldsRequest', () => { it('should include ecs fields by default', () => { const fields: string[] = []; - const fieldsRequest = buildFieldsRequest(fields); - expect(fieldsRequest).toHaveLength(TIMELINE_EVENTS_FIELDS.length); + const fieldsRequest = buildAlertFieldsRequest(fields); + expect(fieldsRequest).toHaveLength(ALERT_EVENTS_FIELDS.length); }); it('should not show ecs fields', () => { const fields: string[] = []; - const fieldsRequest = buildFieldsRequest(fields, true); + const fieldsRequest = buildAlertFieldsRequest(fields, true); expect(fieldsRequest).toHaveLength(0); }); it('should map the expected (non underscore prefixed) fields', () => { const fields = ['_dontShow1', '_dontShow2', 'showsup']; - const fieldsRequest = buildFieldsRequest(fields, true); + const fieldsRequest = buildAlertFieldsRequest(fields, true); expect(fieldsRequest).toEqual([{ field: 'showsup', include_unmapped: true }]); }); it('should map provided fields with ecs fields', () => { const fields = ['showsup']; - const fieldsRequest = buildFieldsRequest(fields); - expect(fieldsRequest).toHaveLength(TIMELINE_EVENTS_FIELDS.length + fields.length); + const fieldsRequest = buildAlertFieldsRequest(fields); + expect(fieldsRequest).toHaveLength(ALERT_EVENTS_FIELDS.length + fields.length); }); }); diff --git a/packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.ts b/packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.ts new file mode 100644 index 0000000000000..07adb71f4a4c0 --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { uniq } from 'lodash/fp'; +import { ALERT_EVENTS_FIELDS } from './fields'; + +export const buildAlertFieldsRequest = (fields: string[], excludeEcsData?: boolean) => + uniq([ + ...fields.filter((field) => !field.startsWith('_')), + ...(excludeEcsData ? [] : ALERT_EVENTS_FIELDS), + ]).map((field) => ({ + field, + include_unmapped: true, + ...(field === '@timestamp' + ? { + format: 'strict_date_optional_time', + } + : {}), + })); diff --git a/packages/kbn-alerts-as-data-utils/src/search/security/fields.ts b/packages/kbn-alerts-as-data-utils/src/search/security/fields.ts new file mode 100644 index 0000000000000..b3be5cbb62a1a --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/search/security/fields.ts @@ -0,0 +1,289 @@ +/* + * Copyright 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 { + ALERT_RULE_CONSUMER, + ALERT_RISK_SCORE, + ALERT_SEVERITY, + ALERT_RULE_PARAMETERS, + ALERT_WORKFLOW_TAGS, +} from '@kbn/rule-data-utils'; + +const ENRICHMENT_DESTINATION_PATH = 'threat.enrichments'; + +const MATCHED_ATOMIC = 'matched.atomic'; +const MATCHED_FIELD = 'matched.field'; +const MATCHED_TYPE = 'matched.type'; + +const INDICATOR_MATCHED_ATOMIC = `${ENRICHMENT_DESTINATION_PATH}.${MATCHED_ATOMIC}`; +const INDICATOR_MATCHED_FIELD = `${ENRICHMENT_DESTINATION_PATH}.${MATCHED_FIELD}`; +const INDICATOR_MATCHED_TYPE = `${ENRICHMENT_DESTINATION_PATH}.${MATCHED_TYPE}`; + +const PROVIDER = 'indicator.provider'; +const REFERENCE = 'indicator.reference'; +const FEED_NAME = 'feed.name'; + +const INDICATOR_PROVIDER = `${ENRICHMENT_DESTINATION_PATH}.${PROVIDER}`; +const INDICATOR_REFERENCE = `${ENRICHMENT_DESTINATION_PATH}.${REFERENCE}`; +const FEED_NAME_REFERENCE = `${ENRICHMENT_DESTINATION_PATH}.${FEED_NAME}`; + +const CTI_ROW_RENDERER_FIELDS = [ + INDICATOR_MATCHED_ATOMIC, + INDICATOR_MATCHED_FIELD, + INDICATOR_MATCHED_TYPE, + INDICATOR_REFERENCE, + INDICATOR_PROVIDER, + FEED_NAME_REFERENCE, +]; + +// TODO: update all of these fields to use the constants from technical field names +export const ALERT_EVENTS_FIELDS = [ + ALERT_RULE_CONSUMER, + '@timestamp', + 'kibana.alert.ancestors.index', + 'kibana.alert.workflow_status', + ALERT_WORKFLOW_TAGS, + 'kibana.alert.group.id', + 'kibana.alert.original_time', + 'kibana.alert.reason', + 'kibana.alert.rule.from', + 'kibana.alert.rule.name', + 'kibana.alert.rule.to', + 'kibana.alert.rule.uuid', + 'kibana.alert.rule.rule_id', + 'kibana.alert.rule.type', + 'kibana.alert.original_event.kind', + 'kibana.alert.original_event.module', + 'kibana.alert.rule.version', + ALERT_SEVERITY, + ALERT_RISK_SCORE, + ALERT_RULE_PARAMETERS, + 'kibana.alert.threshold_result', + 'kibana.alert.building_block_type', + 'kibana.alert.suppression.docs_count', + 'event.code', + 'event.module', + 'event.action', + 'event.category', + 'host.name', + 'user.name', + 'source.ip', + 'destination.ip', + 'message', + 'system.auth.ssh.signature', + 'system.auth.ssh.method', + 'system.audit.package.arch', + 'system.audit.package.entity_id', + 'system.audit.package.name', + 'system.audit.package.size', + 'system.audit.package.summary', + 'system.audit.package.version', + 'event.created', + 'event.dataset', + 'event.duration', + 'event.end', + 'event.hash', + 'event.id', + 'event.kind', + 'event.original', + 'event.outcome', + 'event.risk_score', + 'event.risk_score_norm', + 'event.severity', + 'event.start', + 'event.timezone', + 'event.type', + 'agent.type', + 'agent.id', + 'auditd.result', + 'auditd.session', + 'auditd.data.acct', + 'auditd.data.terminal', + 'auditd.data.op', + 'auditd.summary.actor.primary', + 'auditd.summary.actor.secondary', + 'auditd.summary.object.primary', + 'auditd.summary.object.secondary', + 'auditd.summary.object.type', + 'auditd.summary.how', + 'auditd.summary.message_type', + 'auditd.summary.sequence', + 'file.Ext.original.path', + 'file.name', + 'file.target_path', + 'file.extension', + 'file.type', + 'file.device', + 'file.inode', + 'file.uid', + 'file.owner', + 'file.gid', + 'file.group', + 'file.mode', + 'file.size', + 'file.mtime', + 'file.ctime', + 'file.path', + // NOTE: 7.10+ file.Ext.code_signature populated + // as array of objects, prior to that populated as + // single object + 'file.Ext.code_signature', + 'file.Ext.code_signature.subject_name', + 'file.Ext.code_signature.trusted', + 'file.hash.sha256', + 'host.os.family', + 'host.os.name', + 'host.id', + 'host.ip', + 'registry.key', + 'registry.path', + 'rule.reference', + 'source.bytes', + 'source.packets', + 'source.port', + 'source.geo.continent_name', + 'source.geo.country_name', + 'source.geo.country_iso_code', + 'source.geo.city_name', + 'source.geo.region_iso_code', + 'source.geo.region_name', + 'destination.bytes', + 'destination.packets', + 'destination.port', + 'destination.geo.continent_name', + 'destination.geo.country_name', + 'destination.geo.country_iso_code', + 'destination.geo.city_name', + 'destination.geo.region_iso_code', + 'destination.geo.region_name', + 'dns.question.name', + 'dns.question.type', + 'dns.resolved_ip', + 'dns.response_code', + 'endgame.exit_code', + 'endgame.file_name', + 'endgame.file_path', + 'endgame.logon_type', + 'endgame.parent_process_name', + 'endgame.pid', + 'endgame.process_name', + 'endgame.subject_domain_name', + 'endgame.subject_logon_id', + 'endgame.subject_user_name', + 'endgame.target_domain_name', + 'endgame.target_logon_id', + 'endgame.target_user_name', + 'kibana.alert.rule.timeline_id', + 'kibana.alert.rule.timeline_title', + 'kibana.alert.rule.note', + 'kibana.alert.rule.exceptions_list', + 'kibana.alert.rule.building_block_type', + 'suricata.eve.proto', + 'suricata.eve.flow_id', + 'suricata.eve.alert.signature', + 'suricata.eve.alert.signature_id', + 'network.bytes', + 'network.community_id', + 'network.direction', + 'network.packets', + 'network.protocol', + 'network.transport', + 'http.version', + 'http.request.method', + 'http.request.body.bytes', + 'http.request.body.content', + 'http.request.referrer', + 'http.response.status_code', + 'http.response.body.bytes', + 'http.response.body.content', + 'tls.client_certificate.fingerprint.sha1', + 'tls.fingerprints.ja3.hash', + 'tls.server_certificate.fingerprint.sha1', + 'user.domain', + 'winlog.event_id', + 'process.end', + 'process.entry_leader.entry_meta.type', + 'process.entry_leader.entry_meta.source.ip', + 'process.exit_code', + 'process.hash.md5', + 'process.hash.sha1', + 'process.hash.sha256', + 'process.interactive', + 'process.parent.name', + 'process.parent.pid', + 'process.pid', + 'process.name', + 'process.ppid', + 'process.args', + 'process.entity_id', + 'process.executable', + 'process.start', + 'process.title', + 'process.working_directory', + 'process.entry_leader.entity_id', + 'process.entry_leader.name', + 'process.entry_leader.pid', + 'process.entry_leader.start', + 'process.session_leader.entity_id', + 'process.session_leader.name', + 'process.session_leader.pid', + 'process.group_leader.entity_id', + 'process.group_leader.name', + 'process.group_leader.pid', + 'zeek.session_id', + 'zeek.connection.local_resp', + 'zeek.connection.local_orig', + 'zeek.connection.missed_bytes', + 'zeek.connection.state', + 'zeek.connection.history', + 'zeek.notice.suppress_for', + 'zeek.notice.msg', + 'zeek.notice.note', + 'zeek.notice.sub', + 'zeek.notice.dst', + 'zeek.notice.dropped', + 'zeek.notice.peer_descr', + 'zeek.dns.AA', + 'zeek.dns.qclass_name', + 'zeek.dns.RD', + 'zeek.dns.qtype_name', + 'zeek.dns.qtype', + 'zeek.dns.query', + 'zeek.dns.trans_id', + 'zeek.dns.qclass', + 'zeek.dns.RA', + 'zeek.dns.TC', + 'zeek.http.resp_mime_types', + 'zeek.http.trans_depth', + 'zeek.http.status_msg', + 'zeek.http.resp_fuids', + 'zeek.http.tags', + 'zeek.files.session_ids', + 'zeek.files.timedout', + 'zeek.files.local_orig', + 'zeek.files.tx_host', + 'zeek.files.source', + 'zeek.files.is_orig', + 'zeek.files.overflow_bytes', + 'zeek.files.sha1', + 'zeek.files.duration', + 'zeek.files.depth', + 'zeek.files.analyzers', + 'zeek.files.mime_type', + 'zeek.files.rx_host', + 'zeek.files.total_bytes', + 'zeek.files.fuid', + 'zeek.files.seen_bytes', + 'zeek.files.missing_bytes', + 'zeek.files.md5', + 'zeek.ssl.cipher', + 'zeek.ssl.established', + 'zeek.ssl.resumed', + 'zeek.ssl.version', + ...CTI_ROW_RENDERER_FIELDS, +]; diff --git a/packages/kbn-alerts-as-data-utils/src/search/security/index.ts b/packages/kbn-alerts-as-data-utils/src/search/security/index.ts new file mode 100644 index 0000000000000..0a2b57e8f29ec --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/search/security/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 { buildAlertFieldsRequest } from './build_fields_request'; +export { ALERT_EVENTS_FIELDS } from './fields'; diff --git a/packages/kbn-alerts-ui-shared/index.ts b/packages/kbn-alerts-ui-shared/index.ts index 6815a66bce902..6daec0f82b108 100644 --- a/packages/kbn-alerts-ui-shared/index.ts +++ b/packages/kbn-alerts-ui-shared/index.ts @@ -9,3 +9,4 @@ export { AlertLifecycleStatusBadge } from './src/alert_lifecycle_status_badge'; export type { AlertLifecycleStatusBadgeProps } from './src/alert_lifecycle_status_badge'; export { MaintenanceWindowCallout } from './src/maintenance_window_callout'; +export { AddMessageVariables } from './src/add_message_variables'; diff --git a/packages/kbn-alerts-ui-shared/jest.config.js b/packages/kbn-alerts-ui-shared/jest.config.js index 31062b3280e41..54f2c74a56d3a 100644 --- a/packages/kbn-alerts-ui-shared/jest.config.js +++ b/packages/kbn-alerts-ui-shared/jest.config.js @@ -10,4 +10,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../..', roots: ['/packages/kbn-alerts-ui-shared'], + setupFilesAfterEnv: ['/packages/kbn-alerts-ui-shared/setup_tests.ts'], }; diff --git a/packages/kbn-alerts-ui-shared/setup_tests.ts b/packages/kbn-alerts-ui-shared/setup_tests.ts new file mode 100644 index 0000000000000..8d1acb9232934 --- /dev/null +++ b/packages/kbn-alerts-ui-shared/setup_tests.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. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import '@testing-library/jest-dom'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.scss b/packages/kbn-alerts-ui-shared/src/add_message_variables/add_message_variables.scss similarity index 100% rename from x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.scss rename to packages/kbn-alerts-ui-shared/src/add_message_variables/add_message_variables.scss diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.test.tsx b/packages/kbn-alerts-ui-shared/src/add_message_variables/index.test.tsx similarity index 95% rename from x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.test.tsx rename to packages/kbn-alerts-ui-shared/src/add_message_variables/index.test.tsx index 641587c349382..80603d9eb8615 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/add_message_variables/index.test.tsx @@ -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 React from 'react'; import { render, fireEvent, screen } from '@testing-library/react'; -import { AddMessageVariables } from './add_message_variables'; +import { AddMessageVariables } from '.'; describe('AddMessageVariables', () => { test('it renders variables and filter bar', async () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx b/packages/kbn-alerts-ui-shared/src/add_message_variables/index.tsx similarity index 96% rename from x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx rename to packages/kbn-alerts-ui-shared/src/add_message_variables/index.tsx index f986930470acc..0aa9bae65c29e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx +++ b/packages/kbn-alerts-ui-shared/src/add_message_variables/index.tsx @@ -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 React, { useMemo, useState } from 'react'; @@ -23,7 +24,7 @@ import { } from '@elastic/eui'; import { ActionVariable } from '@kbn/alerting-plugin/common'; import './add_message_variables.scss'; -import { TruncatedText } from '../../common/truncated_text'; +import { TruncatedText } from './truncated_text'; import * as i18n from './translations'; interface Props { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/translations.js b/packages/kbn-alerts-ui-shared/src/add_message_variables/translations.ts similarity index 57% rename from x-pack/plugins/triggers_actions_ui/public/application/components/translations.js rename to packages/kbn-alerts-ui-shared/src/add_message_variables/translations.ts index 0e089f1a830e8..b19e9173797a9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/translations.js +++ b/packages/kbn-alerts-ui-shared/src/add_message_variables/translations.ts @@ -1,70 +1,71 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; 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'; export const LOADING_VARIABLES = i18n.translate( - 'xpack.triggersActionsUI.components.addMessageVariables.loadingMessage', + 'alertsUIShared.components.addMessageVariables.loadingMessage', { defaultMessage: 'Loading variables', } ); export const NO_VARIABLES_FOUND = i18n.translate( - 'xpack.triggersActionsUI.components.addMessageVariables.noVariablesFound', + 'alertsUIShared.components.addMessageVariables.noVariablesFound', { defaultMessage: 'No variables found', } ); export const NO_VARIABLES_AVAILABLE = i18n.translate( - 'xpack.triggersActionsUI.components.addMessageVariables.noVariablesAvailable', + 'alertsUIShared.components.addMessageVariables.noVariablesAvailable', { defaultMessage: 'No variables available', } ); export const DEPRECATED_VARIABLES_ARE_SHOWN = i18n.translate( - 'xpack.triggersActionsUI.components.addMessageVariables.deprecatedVariablesAreShown', + 'alertsUIShared.components.addMessageVariables.deprecatedVariablesAreShown', { defaultMessage: 'Deprecated variables are shown', } ); export const DEPRECATED_VARIABLES_ARE_HIDDEN = i18n.translate( - 'xpack.triggersActionsUI.components.addMessageVariables.deprecatedVariablesAreHidden', + 'alertsUIShared.components.addMessageVariables.deprecatedVariablesAreHidden', { defaultMessage: 'Deprecated variables are hidden', } ); export const HIDE = i18n.translate( - 'xpack.triggersActionsUI.components.addMessageVariables.hideDeprecatedVariables', + 'alertsUIShared.components.addMessageVariables.hideDeprecatedVariables', { defaultMessage: 'Hide', } ); export const SHOW_ALL = i18n.translate( - 'xpack.triggersActionsUI.components.addMessageVariables.showAllDeprecatedVariables', + 'alertsUIShared.components.addMessageVariables.showAllDeprecatedVariables', { defaultMessage: 'Show all', } ); export const ADD_VARIABLE_POPOVER_BUTTON = i18n.translate( - 'xpack.triggersActionsUI.components.addMessageVariables.addVariablePopoverButton', + 'alertsUIShared.components.addMessageVariables.addVariablePopoverButton', { defaultMessage: 'Add variable', } ); export const ADD_VARIABLE_TITLE = i18n.translate( - 'xpack.triggersActionsUI.components.addMessageVariables.addRuleVariableTitle', + 'alertsUIShared.components.addMessageVariables.addRuleVariableTitle', { defaultMessage: 'Add variable', } diff --git a/packages/kbn-alerts-ui-shared/src/add_message_variables/truncated_text.tsx b/packages/kbn-alerts-ui-shared/src/add_message_variables/truncated_text.tsx new file mode 100644 index 0000000000000..52535ab435e68 --- /dev/null +++ b/packages/kbn-alerts-ui-shared/src/add_message_variables/truncated_text.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { css } from '@emotion/react'; +import { EuiText } from '@elastic/eui'; + +const LINE_CLAMP = 2; + +const styles = { + truncatedText: css` + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: ${LINE_CLAMP}; + -webkit-box-orient: vertical; + overflow: hidden; + word-break: break-word; + `, +}; + +const TruncatedTextComponent: React.FC<{ text: string }> = ({ text }) => ( + + {text} + +); + +TruncatedTextComponent.displayName = 'TruncatedText'; + +export const TruncatedText = React.memo(TruncatedTextComponent); diff --git a/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.test.tsx b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.test.tsx index b29f0ddc613c4..9a05a6bd09222 100644 --- a/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/maintenance_window_callout/index.test.tsx @@ -106,7 +106,6 @@ describe('MaintenanceWindowCallout', () => { { wrapper: TestProviders } ); - // @ts-expect-error Jest types are incomplete in packages expect(await findByText('Maintenance window is running')).toBeInTheDocument(); expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); }); @@ -119,7 +118,7 @@ describe('MaintenanceWindowCallout', () => { const { container } = render(, { wrapper: TestProviders, }); - // @ts-expect-error Jest types are incomplete in packages + expect(container).toBeEmptyDOMElement(); expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); }); @@ -130,7 +129,7 @@ describe('MaintenanceWindowCallout', () => { const { container } = render(, { wrapper: TestProviders, }); - // @ts-expect-error Jest types are incomplete in packages + expect(container).toBeEmptyDOMElement(); expect(fetchActiveMaintenanceWindowsMock).toHaveBeenCalledTimes(1); }); @@ -192,7 +191,7 @@ describe('MaintenanceWindowCallout', () => { const { container } = render(, { wrapper: TestProviders, }); - // @ts-expect-error Jest types are incomplete in packages + expect(container).toBeEmptyDOMElement(); }); @@ -213,7 +212,7 @@ describe('MaintenanceWindowCallout', () => { const { findByText } = render(, { wrapper: TestProviders, }); - // @ts-expect-error Jest types are incomplete in packages + expect(await findByText('Maintenance window is running')).toBeInTheDocument(); }); }); diff --git a/packages/kbn-config-mocks/src/config_service.mock.ts b/packages/kbn-config-mocks/src/config_service.mock.ts index 09a282965eba8..268f5a4558022 100644 --- a/packages/kbn-config-mocks/src/config_service.mock.ts +++ b/packages/kbn-config-mocks/src/config_service.mock.ts @@ -27,6 +27,8 @@ const createConfigServiceMock = ({ validate: jest.fn(), getHandledDeprecatedConfigs: jest.fn(), getDeprecatedConfigPath$: jest.fn(), + addDynamicConfigPaths: jest.fn(), + setDynamicConfigOverrides: jest.fn(), }; mocked.atPath.mockReturnValue(new BehaviorSubject(atPath)); diff --git a/packages/kbn-config/src/config_service.test.ts b/packages/kbn-config/src/config_service.test.ts index c38875bdae6ed..434534f6d888a 100644 --- a/packages/kbn-config/src/config_service.test.ts +++ b/packages/kbn-config/src/config_service.test.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import { BehaviorSubject, Observable } from 'rxjs'; -import { first, take } from 'rxjs/operators'; +import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs'; +import { first, map, take } from 'rxjs/operators'; import { mockApplyDeprecations, @@ -670,3 +670,43 @@ describe('getDeprecatedConfigPath$', () => { expect(deprecatedConfigPath).toEqual(mockedChangedPaths); }); }); + +describe('Dynamic Overrides', () => { + let configService: ConfigService; + + beforeEach(async () => { + const rawConfig$ = new BehaviorSubject>({ namespace1: { key: 'value' } }); + const rawConfigProvider = createRawConfigServiceMock({ rawConfig$ }); + + configService = new ConfigService(rawConfigProvider, defaultEnv, logger); + await configService.setSchema('namespace1', schema.object({ key: schema.string() })); + + expect( + await firstValueFrom(configService.getConfig$().pipe(map((cfg) => cfg.toRaw()))) + ).toStrictEqual({ namespace1: { key: 'value' } }); + }); + + test('throws validation error when attempted to set an override that has not been registered as dynamic', () => { + expect(() => + configService.setDynamicConfigOverrides({ 'namespace1.key': 'another-value' }) + ).toThrowErrorMatchingInlineSnapshot(`"[namespace1.key]: not a valid dynamic option"`); + }); + + test('throws validation error when a registered as dynamic option is invalid', () => { + configService.addDynamicConfigPaths('namespace1', ['key']); + expect(() => + configService.setDynamicConfigOverrides({ 'namespace1.key': 1 }) + ).toThrowErrorMatchingInlineSnapshot( + `"[config validation of [namespace1].key]: expected value of type [string] but got [number]"` + ); + }); + + test('overrides the static settings with the dynamic ones', async () => { + configService.addDynamicConfigPaths('namespace1', ['key']); + configService.setDynamicConfigOverrides({ 'namespace1.key': 'another-value' }); + + expect( + await firstValueFrom(configService.getConfig$().pipe(map((cfg) => cfg.toRaw()))) + ).toStrictEqual({ namespace1: { key: 'another-value' } }); + }); +}); diff --git a/packages/kbn-config/src/config_service.ts b/packages/kbn-config/src/config_service.ts index b9ef887e1002c..0026876f70b4d 100644 --- a/packages/kbn-config/src/config_service.ts +++ b/packages/kbn-config/src/config_service.ts @@ -7,16 +7,18 @@ */ import type { PublicMethodsOf } from '@kbn/utility-types'; -import { Type } from '@kbn/config-schema'; -import { isEqual } from 'lodash'; +import { SchemaTypeError, Type, ValidationError } from '@kbn/config-schema'; +import { cloneDeep, isEqual, merge } from 'lodash'; +import { set } from '@kbn/safer-lodash-set'; import { BehaviorSubject, combineLatest, firstValueFrom, Observable } from 'rxjs'; import { distinctUntilChanged, first, map, shareReplay, tap } from 'rxjs/operators'; import { Logger, LoggerFactory } from '@kbn/logging'; import { getDocLinks, DocLinks } from '@kbn/doc-links'; +import { getFlattenedObject } from '@kbn/std'; import { Config, ConfigPath, Env } from '..'; import { hasConfigPathIntersection } from './config'; -import { RawConfigurationProvider } from './raw/raw_config_service'; +import { RawConfigurationProvider } from './raw'; import { applyDeprecations, ConfigDeprecationWithContext, @@ -60,6 +62,8 @@ export class ConfigService { private readonly handledPaths: Set = new Set(); private readonly schemas = new Map>(); private readonly deprecations = new BehaviorSubject([]); + private readonly dynamicPaths = new Map(); + private readonly overrides$ = new BehaviorSubject>({}); private readonly handledDeprecatedConfigs = new Map(); constructor( @@ -71,9 +75,14 @@ export class ConfigService { this.deprecationLog = logger.get('config', 'deprecation'); this.docLinks = getDocLinks({ kibanaBranch: env.packageInfo.branch }); - this.config$ = combineLatest([this.rawConfigProvider.getConfig$(), this.deprecations]).pipe( - map(([rawConfig, deprecations]) => { - const migrated = applyDeprecations(rawConfig, deprecations); + this.config$ = combineLatest([ + this.rawConfigProvider.getConfig$(), + this.deprecations, + this.overrides$, + ]).pipe( + map(([rawConfig, deprecations, overrides]) => { + const overridden = merge(rawConfig, overrides); + const migrated = applyDeprecations(overridden, deprecations); this.deprecatedConfigPaths.next(migrated.changedPaths); return new ObjectToConfigAdapter(migrated.config); }), @@ -213,6 +222,59 @@ export class ConfigService { return this.deprecatedConfigPaths.asObservable(); } + /** + * Adds a specific setting to be allowed to change dynamically. + * @param configPath The namespace of the config + * @param dynamicConfigPaths The config keys that can be dynamically changed + */ + public addDynamicConfigPaths(configPath: ConfigPath, dynamicConfigPaths: string[]) { + const _configPath = Array.isArray(configPath) ? configPath.join('.') : configPath; + this.dynamicPaths.set(_configPath, dynamicConfigPaths); + } + + /** + * Used for dynamically extending the overrides. + * These overrides are not persisted and will be discarded after restarts. + * @param newOverrides + */ + public setDynamicConfigOverrides(newOverrides: Record) { + const globalOverrides = cloneDeep(this.overrides$.value); + + const flattenedOverrides = getFlattenedObject(newOverrides); + + const validateWithNamespace = new Set(); + + keyLoop: for (const key in flattenedOverrides) { + // this if is enforced by an eslint rule :shrug: + if (key in flattenedOverrides) { + for (const [configPath, dynamicConfigKeys] of this.dynamicPaths.entries()) { + if ( + key.startsWith(`${configPath}.`) && + dynamicConfigKeys.some( + // The key is explicitly allowed OR its prefix is + (dynamicConfigKey) => + key === `${configPath}.${dynamicConfigKey}` || + key.startsWith(`${configPath}.${dynamicConfigKey}.`) + ) + ) { + validateWithNamespace.add(configPath); + set(globalOverrides, key, flattenedOverrides[key]); + continue keyLoop; + } + } + throw new ValidationError(new SchemaTypeError(`not a valid dynamic option`, [key])); + } + } + + const globalOverridesAsConfig = new ObjectToConfigAdapter( + merge({}, this.lastConfig, globalOverrides) + ); + + validateWithNamespace.forEach((ns) => this.validateAtPath(ns, globalOverridesAsConfig.get(ns))); + + this.overrides$.next(globalOverrides); + } + private async logDeprecation() { const rawConfig = await firstValueFrom(this.rawConfigProvider.getConfig$()); const deprecations = await firstValueFrom(this.deprecations); diff --git a/packages/kbn-dev-utils/index.ts b/packages/kbn-dev-utils/index.ts index 86bdafebccf97..2faf0000fde29 100644 --- a/packages/kbn-dev-utils/index.ts +++ b/packages/kbn-dev-utils/index.ts @@ -19,6 +19,7 @@ export { KBN_P12_PATH, KBN_P12_PASSWORD, } from './src/certs'; +export * from './src/dev_service_account'; export * from './src/axios'; export * from './src/plugin_list'; export * from './src/streams'; diff --git a/packages/kbn-dev-utils/src/dev_service_account.ts b/packages/kbn-dev-utils/src/dev_service_account.ts new file mode 100644 index 0000000000000..efcd51b3f1559 --- /dev/null +++ b/packages/kbn-dev-utils/src/dev_service_account.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +const env = process.env; + +/** + * `kibana-dev` service account token for connecting to ESS + * See packages/kbn-es/src/ess_resources/README.md + */ +export const kibanaDevServiceAccount = { + token: + env.TEST_KIBANA_SERVICE_ACCOUNT_TOKEN || + 'AAEAAWVsYXN0aWMva2liYW5hL2tpYmFuYS1kZXY6VVVVVVVVTEstKiBaNA', +}; diff --git a/packages/kbn-discover-utils/index.ts b/packages/kbn-discover-utils/index.ts index dae9c268f80db..d19f50c5dc646 100644 --- a/packages/kbn-discover-utils/index.ts +++ b/packages/kbn-discover-utils/index.ts @@ -13,9 +13,11 @@ export { DEFAULT_COLUMNS_SETTING, DOC_HIDE_TIME_COLUMN_SETTING, DOC_TABLE_LEGACY, - ENABLE_SQL, + ENABLE_ESQL, FIELDS_LIMIT_SETTING, HIDE_ANNOUNCEMENTS, + KNOWN_FIELD_TYPE_LIST, + KNOWN_FIELD_TYPES, MAX_DOC_FIELDS_DISPLAYED, MODIFY_COLUMNS_ON_SWITCH, ROW_HEIGHT_OPTION, @@ -34,8 +36,10 @@ export { formatFieldValue, formatHit, getDocId, + getFieldTypeName, getIgnoredReason, getShouldShowFieldHandler, + isKnownFieldType, isNestedFieldParent, usePager, } from './src'; diff --git a/packages/kbn-discover-utils/src/constants.ts b/packages/kbn-discover-utils/src/constants.ts index 60aaf63d9c70e..7582b610c6638 100644 --- a/packages/kbn-discover-utils/src/constants.ts +++ b/packages/kbn-discover-utils/src/constants.ts @@ -12,7 +12,7 @@ export const CONTEXT_TIE_BREAKER_FIELDS_SETTING = 'context:tieBreakerFields'; export const DEFAULT_COLUMNS_SETTING = 'defaultColumns'; export const DOC_HIDE_TIME_COLUMN_SETTING = 'doc_table:hideTimeColumn'; export const DOC_TABLE_LEGACY = 'doc_table:legacy'; -export const ENABLE_SQL = 'discover:enableSql'; +export const ENABLE_ESQL = 'discover:enableESQL'; export const FIELDS_LIMIT_SETTING = 'fields:popularLimit'; export const HIDE_ANNOUNCEMENTS = 'hideAnnouncements'; export const MAX_DOC_FIELDS_DISPLAYED = 'discover:maxDocFieldsDisplayed'; diff --git a/packages/kbn-discover-utils/src/types.ts b/packages/kbn-discover-utils/src/types.ts index 752de1dcb9e9d..5a2f3ed9b085e 100644 --- a/packages/kbn-discover-utils/src/types.ts +++ b/packages/kbn-discover-utils/src/types.ts @@ -8,7 +8,7 @@ import type { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -export type { IgnoredReason, ShouldShowFieldInTableHandler } from './utils'; +export type { FieldTypeKnown, IgnoredReason, ShouldShowFieldInTableHandler } from './utils'; export interface EsHitRecord extends Omit { _source?: Record; diff --git a/packages/kbn-unified-field-list/src/utils/field_types/field_types.ts b/packages/kbn-discover-utils/src/utils/field_types.ts similarity index 87% rename from packages/kbn-unified-field-list/src/utils/field_types/field_types.ts rename to packages/kbn-discover-utils/src/utils/field_types.ts index 0851d6dc1e412..320f606dd0d8e 100644 --- a/packages/kbn-unified-field-list/src/utils/field_types/field_types.ts +++ b/packages/kbn-discover-utils/src/utils/field_types.ts @@ -6,7 +6,12 @@ * Side Public License, v 1. */ -import { FieldTypeKnown } from '../../types'; +import type { DataViewField } from '@kbn/data-views-plugin/common'; + +export type FieldTypeKnown = Exclude< + DataViewField['timeSeriesMetric'] | DataViewField['type'], + undefined +>; /** * Field types for which name and description are defined diff --git a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_name.test.ts b/packages/kbn-discover-utils/src/utils/get_field_type_name.test.ts similarity index 100% rename from packages/kbn-unified-field-list/src/utils/field_types/get_field_type_name.test.ts rename to packages/kbn-discover-utils/src/utils/get_field_type_name.test.ts diff --git a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_name.ts b/packages/kbn-discover-utils/src/utils/get_field_type_name.ts similarity index 59% rename from packages/kbn-unified-field-list/src/utils/field_types/get_field_type_name.ts rename to packages/kbn-discover-utils/src/utils/get_field_type_name.ts index 23ae35a4c2ef3..7e7bd102f3353 100644 --- a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_name.ts +++ b/packages/kbn-discover-utils/src/utils/get_field_type_name.ts @@ -14,7 +14,7 @@ import { KNOWN_FIELD_TYPES } from './field_types'; * A user-friendly name of an unknown field type */ export const UNKNOWN_FIELD_TYPE_MESSAGE = i18n.translate( - 'unifiedFieldList.fieldNameIcons.unknownFieldAriaLabel', + 'discover.fieldNameIcons.unknownFieldAriaLabel', { defaultMessage: 'Unknown field', } @@ -32,7 +32,7 @@ export function getFieldTypeName(type?: string) { if (type === 'source') { // Note that this type is currently not provided, type for _source is undefined - return i18n.translate('unifiedFieldList.fieldNameIcons.sourceFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.sourceFieldAriaLabel', { defaultMessage: 'Source field', }); } @@ -40,107 +40,107 @@ export function getFieldTypeName(type?: string) { const knownType: KNOWN_FIELD_TYPES = type as KNOWN_FIELD_TYPES; switch (knownType) { case KNOWN_FIELD_TYPES.DOCUMENT: - return i18n.translate('unifiedFieldList.fieldNameIcons.recordAriaLabel', { + return i18n.translate('discover.fieldNameIcons.recordAriaLabel', { defaultMessage: 'Records', }); case KNOWN_FIELD_TYPES.BINARY: - return i18n.translate('unifiedFieldList.fieldNameIcons.binaryAriaLabel', { + return i18n.translate('discover.fieldNameIcons.binaryAriaLabel', { defaultMessage: 'Binary', }); case KNOWN_FIELD_TYPES.BOOLEAN: - return i18n.translate('unifiedFieldList.fieldNameIcons.booleanAriaLabel', { + return i18n.translate('discover.fieldNameIcons.booleanAriaLabel', { defaultMessage: 'Boolean', }); case KNOWN_FIELD_TYPES.CONFLICT: - return i18n.translate('unifiedFieldList.fieldNameIcons.conflictFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.conflictFieldAriaLabel', { defaultMessage: 'Conflict', }); case KNOWN_FIELD_TYPES.COUNTER: - return i18n.translate('unifiedFieldList.fieldNameIcons.counterFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.counterFieldAriaLabel', { defaultMessage: 'Counter metric', }); case KNOWN_FIELD_TYPES.DATE: - return i18n.translate('unifiedFieldList.fieldNameIcons.dateFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.dateFieldAriaLabel', { defaultMessage: 'Date', }); case KNOWN_FIELD_TYPES.DATE_RANGE: - return i18n.translate('unifiedFieldList.fieldNameIcons.dateRangeFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.dateRangeFieldAriaLabel', { defaultMessage: 'Date range', }); case KNOWN_FIELD_TYPES.DENSE_VECTOR: - return i18n.translate('unifiedFieldList.fieldNameIcons.denseVectorFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.denseVectorFieldAriaLabel', { defaultMessage: 'Dense vector', }); case KNOWN_FIELD_TYPES.GAUGE: - return i18n.translate('unifiedFieldList.fieldNameIcons.gaugeFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.gaugeFieldAriaLabel', { defaultMessage: 'Gauge metric', }); case KNOWN_FIELD_TYPES.GEO_POINT: - return i18n.translate('unifiedFieldList.fieldNameIcons.geoPointFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.geoPointFieldAriaLabel', { defaultMessage: 'Geo point', }); case KNOWN_FIELD_TYPES.GEO_SHAPE: - return i18n.translate('unifiedFieldList.fieldNameIcons.geoShapeFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.geoShapeFieldAriaLabel', { defaultMessage: 'Geo shape', }); case KNOWN_FIELD_TYPES.HISTOGRAM: - return i18n.translate('unifiedFieldList.fieldNameIcons.histogramFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.histogramFieldAriaLabel', { defaultMessage: 'Histogram', }); case KNOWN_FIELD_TYPES.IP: - return i18n.translate('unifiedFieldList.fieldNameIcons.ipAddressFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.ipAddressFieldAriaLabel', { defaultMessage: 'IP address', }); case KNOWN_FIELD_TYPES.IP_RANGE: - return i18n.translate('unifiedFieldList.fieldNameIcons.ipRangeFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.ipRangeFieldAriaLabel', { defaultMessage: 'IP range', }); case KNOWN_FIELD_TYPES.FLATTENED: - return i18n.translate('unifiedFieldList.fieldNameIcons.flattenedFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.flattenedFieldAriaLabel', { defaultMessage: 'Flattened', }); case KNOWN_FIELD_TYPES.MURMUR3: - return i18n.translate('unifiedFieldList.fieldNameIcons.murmur3FieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.murmur3FieldAriaLabel', { defaultMessage: 'Murmur3', }); case KNOWN_FIELD_TYPES.NUMBER: - return i18n.translate('unifiedFieldList.fieldNameIcons.numberFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.numberFieldAriaLabel', { defaultMessage: 'Number', }); case KNOWN_FIELD_TYPES.RANK_FEATURE: - return i18n.translate('unifiedFieldList.fieldNameIcons.rankFeatureFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.rankFeatureFieldAriaLabel', { defaultMessage: 'Rank feature', }); case KNOWN_FIELD_TYPES.RANK_FEATURES: - return i18n.translate('unifiedFieldList.fieldNameIcons.rankFeaturesFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.rankFeaturesFieldAriaLabel', { defaultMessage: 'Rank features', }); case KNOWN_FIELD_TYPES.POINT: - return i18n.translate('unifiedFieldList.fieldNameIcons.pointFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.pointFieldAriaLabel', { defaultMessage: 'Point', }); case KNOWN_FIELD_TYPES.SHAPE: - return i18n.translate('unifiedFieldList.fieldNameIcons.shapeFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.shapeFieldAriaLabel', { defaultMessage: 'Shape', }); case KNOWN_FIELD_TYPES.STRING: - return i18n.translate('unifiedFieldList.fieldNameIcons.stringFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.stringFieldAriaLabel', { defaultMessage: 'String', }); case KNOWN_FIELD_TYPES.TEXT: - return i18n.translate('unifiedFieldList.fieldNameIcons.textFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.textFieldAriaLabel', { defaultMessage: 'Text', }); case KNOWN_FIELD_TYPES.KEYWORD: - return i18n.translate('unifiedFieldList.fieldNameIcons.keywordFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.keywordFieldAriaLabel', { defaultMessage: 'Keyword', }); case KNOWN_FIELD_TYPES.NESTED: - return i18n.translate('unifiedFieldList.fieldNameIcons.nestedFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.nestedFieldAriaLabel', { defaultMessage: 'Nested', }); case KNOWN_FIELD_TYPES.VERSION: - return i18n.translate('unifiedFieldList.fieldNameIcons.versionFieldAriaLabel', { + return i18n.translate('discover.fieldNameIcons.versionFieldAriaLabel', { defaultMessage: 'Version', }); default: diff --git a/packages/kbn-discover-utils/src/utils/index.ts b/packages/kbn-discover-utils/src/utils/index.ts index 4828fcf82a447..fc8288f533deb 100644 --- a/packages/kbn-discover-utils/src/utils/index.ts +++ b/packages/kbn-discover-utils/src/utils/index.ts @@ -7,9 +7,11 @@ */ export * from './build_data_record'; +export * from './field_types'; export * from './format_hit'; export * from './format_value'; export * from './get_doc_id'; +export * from './get_field_type_name'; export * from './get_ignored_reason'; export * from './get_should_show_field_handler'; export * from './nested_fields'; diff --git a/packages/kbn-discover-utils/src/utils/nested_fields.test.ts b/packages/kbn-discover-utils/src/utils/nested_fields.test.ts new file mode 100644 index 0000000000000..b2e74a556e8f7 --- /dev/null +++ b/packages/kbn-discover-utils/src/utils/nested_fields.test.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { DataView } from '@kbn/data-views-plugin/common'; +import { isNestedFieldParent } from './nested_fields'; +describe('isNestedFieldParent', () => { + it('correctly identifies nested parent fields', () => { + const nestedField = { + name: 'nested.field', + type: 'keyword', + subType: { + nested: { + path: 'nested.field.path', + }, + }, + }; + const unnestedField = { + name: 'unnested.field', + type: 'keyword', + }; + const list = [nestedField, unnestedField]; + + const dataView = { + fields: { + getByName: jest.fn((fieldName) => list.find((field) => field.name === fieldName)), + getAll: jest.fn(() => list), + }, + } as unknown as DataView; + + expect(isNestedFieldParent('nested', dataView)).toBe(true); + expect(isNestedFieldParent('nested.field', dataView)).toBe(false); + expect(isNestedFieldParent('unnested.field', dataView)).toBe(false); + expect(isNestedFieldParent('whateverField', dataView)).toBe(false); + }); +}); diff --git a/packages/kbn-discover-utils/src/utils/nested_fields.ts b/packages/kbn-discover-utils/src/utils/nested_fields.ts index 9b7fe693ce22e..d4930b63832fd 100644 --- a/packages/kbn-discover-utils/src/utils/nested_fields.ts +++ b/packages/kbn-discover-utils/src/utils/nested_fields.ts @@ -47,12 +47,15 @@ import type { DataView } from '@kbn/data-views-plugin/public'; * issue: https://github.com/elastic/kibana/issues/54957 */ export function isNestedFieldParent(fieldName: string, dataView: DataView): boolean { + const nestedRootRegex = new RegExp(escapeRegExp(fieldName) + '(\\.|$)'); return ( !dataView.fields.getByName(fieldName) && !!dataView.fields.getAll().find((patternField) => { // We only want to match a full path segment - const nestedRootRegex = new RegExp(escapeRegExp(fieldName) + '(\\.|$)'); const subTypeNested = getDataViewFieldSubtypeNested(patternField); + if (!subTypeNested) { + return false; + } return nestedRootRegex.test(subTypeNested?.nested.path ?? ''); }) ); diff --git a/packages/kbn-discover-utils/types.ts b/packages/kbn-discover-utils/types.ts index 69ea11ea628d8..ea9c48f34c39f 100644 --- a/packages/kbn-discover-utils/types.ts +++ b/packages/kbn-discover-utils/types.ts @@ -9,6 +9,7 @@ export type { DataTableRecord, EsHitRecord, + FieldTypeKnown, IgnoredReason, ShouldShowFieldInTableHandler, } from './src/types'; diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 1b1973e35ec52..a8d63137fa0a9 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -622,6 +622,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { }, apis: { bulkIndexAlias: `${ELASTICSEARCH_DOCS}indices-aliases.html`, + indexStats: `${ELASTICSEARCH_DOCS}indices-stats.html`, byteSizeUnits: `${ELASTICSEARCH_DOCS}api-conventions.html#byte-units`, createAutoFollowPattern: `${ELASTICSEARCH_DOCS}ccr-put-auto-follow-pattern.html`, createFollower: `${ELASTICSEARCH_DOCS}ccr-put-follow.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index b29017f71d739..428ef86267dd1 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -361,6 +361,7 @@ export interface DocLinks { readonly visualize: Record; readonly apis: Readonly<{ bulkIndexAlias: string; + indexStats: string; byteSizeUnits: string; createAutoFollowPattern: string; createFollower: string; diff --git a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts index 2c23eec3ca2aa..42df7340c1853 100644 --- a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts +++ b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts @@ -8,25 +8,15 @@ import type { Client } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/tooling-log'; -import { KbnClient } from '@kbn/test'; import { ALL_SAVED_OBJECT_INDICES } from '@kbn/core-saved-objects-server'; -import { migrateSavedObjectIndices, createStats, cleanSavedObjectIndices } from '../lib'; +import { createStats, cleanSavedObjectIndices } from '../lib'; -export async function emptyKibanaIndexAction({ - client, - log, - kbnClient, -}: { - client: Client; - log: ToolingLog; - kbnClient: KbnClient; -}) { +export async function emptyKibanaIndexAction({ client, log }: { client: Client; log: ToolingLog }) { const stats = createStats('emptyKibanaIndex', log); await cleanSavedObjectIndices({ client, stats, log }); - await migrateSavedObjectIndices(kbnClient); await client.indices.refresh({ index: ALL_SAVED_OBJECT_INDICES }); - ALL_SAVED_OBJECT_INDICES.forEach((indexPattern) => stats.createdIndex(indexPattern)); + return stats.toJSON(); } diff --git a/packages/kbn-es-archiver/src/es_archiver.ts b/packages/kbn-es-archiver/src/es_archiver.ts index 65de41148d8db..d5c989f080486 100644 --- a/packages/kbn-es-archiver/src/es_archiver.ts +++ b/packages/kbn-es-archiver/src/es_archiver.ts @@ -154,14 +154,12 @@ export class EsArchiver { } /** - * Delete any Kibana indices, and initialize the Kibana index as Kibana would do - * on startup. + * Cleanup saved object indices, preserving the space:default saved object. */ async emptyKibanaIndex() { return await emptyKibanaIndexAction({ client: this.client, log: this.log, - kbnClient: this.kbnClient, }); } diff --git a/packages/kbn-es-query/index.ts b/packages/kbn-es-query/index.ts index 1e0d9092adefb..a14724fc3a748 100644 --- a/packages/kbn-es-query/index.ts +++ b/packages/kbn-es-query/index.ts @@ -54,6 +54,8 @@ export { isOfAggregateQueryType, getAggregateQueryMode, getIndexPatternFromSQLQuery, + getIndexPatternFromESQLQuery, + getLanguageDisplayName, } from './src/es_query'; export { diff --git a/packages/kbn-es-query/src/es_query/build_es_query.ts b/packages/kbn-es-query/src/es_query/build_es_query.ts index 9d1b0b1c6b139..ff9908bcb0cc3 100644 --- a/packages/kbn-es-query/src/es_query/build_es_query.ts +++ b/packages/kbn-es-query/src/es_query/build_es_query.ts @@ -12,7 +12,7 @@ import { buildQueryFromKuery } from './from_kuery'; import { buildQueryFromFilters } from './from_filters'; import { buildQueryFromLucene } from './from_lucene'; import { Filter, Query, AggregateQuery } from '../filters'; -import { isOfQueryType } from './es_query_sql'; +import { isOfQueryType } from './es_aggregate_query'; import { BoolQuery, DataViewBase } from './types'; import type { KueryQueryOptions } from '../kuery'; import type { EsQueryFiltersConfig } from './from_filters'; diff --git a/packages/kbn-es-query/src/es_query/es_query_sql.test.ts b/packages/kbn-es-query/src/es_query/es_aggregate_query.test.ts similarity index 81% rename from packages/kbn-es-query/src/es_query/es_query_sql.test.ts rename to packages/kbn-es-query/src/es_query/es_aggregate_query.test.ts index da909c6e5f9b4..2ab161e0f7517 100644 --- a/packages/kbn-es-query/src/es_query/es_query_sql.test.ts +++ b/packages/kbn-es-query/src/es_query/es_aggregate_query.test.ts @@ -11,7 +11,8 @@ import { isOfAggregateQueryType, getAggregateQueryMode, getIndexPatternFromSQLQuery, -} from './es_query_sql'; + getIndexPatternFromESQLQuery, +} from './es_aggregate_query'; describe('sql query helpers', () => { describe('isOfQueryType', () => { @@ -81,4 +82,20 @@ describe('sql query helpers', () => { expect(idxPattern8).toBe('logstash-1234!'); }); }); + + describe('getIndexPatternFromESQLQuery', () => { + it('should return the index pattern string from esql queries', () => { + const idxPattern1 = getIndexPatternFromESQLQuery('FROM foo'); + expect(idxPattern1).toBe('foo'); + + const idxPattern3 = getIndexPatternFromESQLQuery('from foo | project abc, def'); + expect(idxPattern3).toBe('foo'); + + const idxPattern4 = getIndexPatternFromESQLQuery('from foo | project a | limit 2'); + expect(idxPattern4).toBe('foo'); + + const idxPattern5 = getIndexPatternFromESQLQuery('from foo | limit 2'); + expect(idxPattern5).toBe('foo'); + }); + }); }); diff --git a/packages/kbn-es-query/src/es_query/es_query_sql.ts b/packages/kbn-es-query/src/es_query/es_aggregate_query.ts similarity index 67% rename from packages/kbn-es-query/src/es_query/es_query_sql.ts rename to packages/kbn-es-query/src/es_query/es_aggregate_query.ts index 46de33dc04e86..1e87552e98b83 100644 --- a/packages/kbn-es-query/src/es_query/es_query_sql.ts +++ b/packages/kbn-es-query/src/es_query/es_aggregate_query.ts @@ -28,7 +28,11 @@ export function getAggregateQueryMode(query: AggregateQuery): Language { return Object.keys(query)[0] as Language; } -// retrieves the index pattern from the aggregate query +export function getLanguageDisplayName(language: string): string { + return language === 'esql' ? 'es|ql' : language; +} + +// retrieves the index pattern from the aggregate query for SQL export function getIndexPatternFromSQLQuery(sqlQuery?: string): string { let sql = sqlQuery?.replaceAll('"', '').replaceAll("'", ''); const splitFroms = sql?.split(new RegExp(/FROM\s/, 'ig')); @@ -44,3 +48,20 @@ export function getIndexPatternFromSQLQuery(sqlQuery?: string): string { } return ''; } + +// retrieves the index pattern from the aggregate query for ES|QL +export function getIndexPatternFromESQLQuery(esql?: string): string { + const splitFroms = esql?.split(new RegExp(/FROM\s/, 'ig')); + const fromsLength = splitFroms?.length ?? 0; + if (splitFroms && splitFroms?.length > 2) { + esql = `${splitFroms[fromsLength - 2]} FROM ${splitFroms[fromsLength - 1]}`; + } + const parsedString = esql?.replaceAll('`', ''); + // case insensitive match for the index pattern + const regex = new RegExp(/FROM\s+([\w*-.!@$^()~;]+)/, 'i'); + const matches = parsedString?.match(regex); + if (matches) { + return matches[1]; + } + return ''; +} diff --git a/packages/kbn-es-query/src/es_query/index.ts b/packages/kbn-es-query/src/es_query/index.ts index 1dca3a5524cfb..22141a52e93f5 100644 --- a/packages/kbn-es-query/src/es_query/index.ts +++ b/packages/kbn-es-query/src/es_query/index.ts @@ -18,7 +18,9 @@ export { isOfAggregateQueryType, getAggregateQueryMode, getIndexPatternFromSQLQuery, -} from './es_query_sql'; + getLanguageDisplayName, + getIndexPatternFromESQLQuery, +} from './es_aggregate_query'; export { fromCombinedFilter } from './from_combined_filter'; export type { IFieldSubType, diff --git a/packages/kbn-es/README.mdx b/packages/kbn-es/README.mdx index e6e5727ccb897..90bc36bc1da58 100644 --- a/packages/kbn-es/README.mdx +++ b/packages/kbn-es/README.mdx @@ -10,13 +10,19 @@ tags: ['kibana', 'dev', 'contributor', 'operations', 'es'] > A command line utility for running elasticsearch from snapshot, source, archive, docker, serverless or even building snapshot artifacts. ## Getting started +To run, go to the Kibana root and run `node scripts/es --help` to get the latest command line options. + +The script attempts to preserve the existing interfaces used by Elasticsearch CLI. This includes passing through options with the `-E` argument and the `ES_JAVA_OPTS` environment variable for Java options. + If running elasticsearch from source, elasticsearch needs to be cloned to a sibling directory of Kibana. -If running elasticsearch serverless or a docker container, docker is required to be installed locally. Installation instructions can be found [here](https://www.docker.com/). +### Serverless & Docker Prerequisites +If running elasticsearch serverless or a docker container, there is some required initial setup: -To run, go to the Kibana root and run `node scripts/es --help` to get the latest command line options. +1. Install Docker. Instructions can be found [here](https://www.docker.com/). +1. Authentication with Elastic's Docker registry [here](https://docker-auth.elastic.co/github_auth). +1. Increase OS virtual memory limits. More info in the [ES docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html). -The script attempts to preserve the existing interfaces used by Elasticsearch CLI. This includes passing through options with the `-E` argument and the `ES_JAVA_OPTS` environment variable for Java options. ### Examples diff --git a/packages/kbn-es/index.ts b/packages/kbn-es/index.ts index aed2ab7af41c5..3ccb220be6b52 100644 --- a/packages/kbn-es/index.ts +++ b/packages/kbn-es/index.ts @@ -8,4 +8,9 @@ export { run } from './src/cli'; export { Cluster } from './src/cluster'; -export { SYSTEM_INDICES_SUPERUSER } from './src/utils'; +export { + SYSTEM_INDICES_SUPERUSER, + ELASTIC_SERVERLESS_SUPERUSER, + ELASTIC_SERVERLESS_SUPERUSER_PASSWORD, + getDockerFileMountPath, +} from './src/utils'; diff --git a/packages/kbn-es/src/cli_commands/docker.ts b/packages/kbn-es/src/cli_commands/docker.ts index cb5a57731b907..aad68bf0a1dae 100644 --- a/packages/kbn-es/src/cli_commands/docker.ts +++ b/packages/kbn-es/src/cli_commands/docker.ts @@ -12,7 +12,7 @@ import { ToolingLog } from '@kbn/tooling-log'; import { getTimeReporter } from '@kbn/ci-stats-reporter'; import { Cluster } from '../cluster'; -import { DOCKER_IMG, DOCKER_REPO, DOCKER_TAG } from '../utils'; +import { DOCKER_IMG, DOCKER_REPO, DOCKER_TAG, DEFAULT_PORT } from '../utils'; import { Command } from './types'; export const docker: Command = { @@ -27,8 +27,12 @@ export const docker: Command = { --tag Image tag of ES to run from ${DOCKER_REPO} [default: ${DOCKER_TAG}] --image Full path to image of ES to run, has precedence over tag. [default: ${DOCKER_IMG}] --password Sets password for elastic user [default: ${password}] + --port The port to bind to on 127.0.0.1 [default: ${DEFAULT_PORT}] + --ssl Sets up SSL and enables security plugin on Elasticsearch + --kill Kill running ES nodes if detected -E Additional key=value settings to pass to Elasticsearch -D Override Docker command + -F Absolute paths for files to mount into container Examples: @@ -50,9 +54,11 @@ export const docker: Command = { alias: { esArgs: 'E', dockerCmd: 'D', + files: 'F', }, string: ['tag', 'image', 'D'], + boolean: ['ssl', 'kill'], default: defaults, }); diff --git a/packages/kbn-es/src/cli_commands/serverless.ts b/packages/kbn-es/src/cli_commands/serverless.ts index ab2d6d4b63926..51cc1b619017a 100644 --- a/packages/kbn-es/src/cli_commands/serverless.ts +++ b/packages/kbn-es/src/cli_commands/serverless.ts @@ -11,8 +11,8 @@ import getopts from 'getopts'; import { ToolingLog } from '@kbn/tooling-log'; import { getTimeReporter } from '@kbn/ci-stats-reporter'; -import { Cluster } from '../cluster'; -import { SERVERLESS_REPO, SERVERLESS_TAG, SERVERLESS_IMG } from '../utils'; +import { Cluster, type ServerlessOptions } from '../cluster'; +import { SERVERLESS_REPO, SERVERLESS_TAG, SERVERLESS_IMG, DEFAULT_PORT } from '../utils'; import { Command } from './types'; export const serverless: Command = { @@ -22,10 +22,15 @@ export const serverless: Command = { return dedent` Options: - --tag Image tag of ES Serverless to run from ${SERVERLESS_REPO} [default: ${SERVERLESS_TAG}] - --image Full path of ES Serverless image to run, has precedence over tag. [default: ${SERVERLESS_IMG}] + --tag Image tag of ESS to run from ${SERVERLESS_REPO} [default: ${SERVERLESS_TAG}] + --image Full path of ESS image to run, has precedence over tag. [default: ${SERVERLESS_IMG}] --clean Remove existing file system object store before running + --port The port to bind to on 127.0.0.1 [default: ${DEFAULT_PORT}] + --ssl Sets up SSL and enables security plugin on Elasticsearch + --kill Kill running ESS nodes if detected + --background Start ESS without attaching to the first node's logs -E Additional key=value settings to pass to Elasticsearch + -F Absolute paths for files to mount into containers Examples: @@ -46,13 +51,14 @@ export const serverless: Command = { alias: { basePath: 'base-path', esArgs: 'E', + files: 'F', }, string: ['tag', 'image'], - boolean: ['clean'], + boolean: ['clean', 'ssl', 'kill', 'background'], default: defaults, - }); + }) as unknown as ServerlessOptions; const cluster = new Cluster(); await cluster.runServerless({ diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index b88e4a788fb72..084cb9c601578 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -16,13 +16,15 @@ const { Client } = require('@elastic/elasticsearch'); const { downloadSnapshot, installSnapshot, installSource, installArchive } = require('./install'); const { ES_BIN, ES_PLUGIN_BIN, ES_KEYSTORE_BIN } = require('./paths'); const { - log: defaultLog, - parseEsLog, extractConfigFiles, + log: defaultLog, NativeRealm, + parseEsLog, parseTimeoutToMs, - runServerlessCluster, runDockerContainer, + runServerlessCluster, + stopServerlessCluster, + teardownServerlessClusterSync, } = require('./utils'); const { createCliError } = require('./errors'); const { promisify } = require('util'); @@ -34,7 +36,7 @@ const DEFAULT_READY_TIMEOUT = parseTimeoutToMs('1m'); /** @typedef {import('./cluster_exec_options').EsClusterExecOptions} ExecOptions */ /** @typedef {import('./utils').DockerOptions} DockerOptions */ -/** @typedef {import('./utils').ServerlessOptions}ServerlessrOptions */ +/** @typedef {import('./utils').ServerlessOptions}ServerlessOptions */ // listen to data on stream until map returns anything but undefined const first = (stream, map) => @@ -276,6 +278,10 @@ exports.Cluster = class Cluster { } this._stopCalled = true; + if (this._serverlessNodes?.length) { + return await stopServerlessCluster(this._log, this._serverlessNodes); + } + if (!this._process || !this._outcome) { throw new Error('ES has not been started'); } @@ -295,6 +301,10 @@ exports.Cluster = class Cluster { this._stopCalled; + if (this._serverlessNodes?.length) { + return await stopServerlessCluster(this._log, this._serverlessNodes); + } + if (!this._process || !this._outcome) { throw new Error('ES has not been started'); } @@ -573,7 +583,15 @@ exports.Cluster = class Cluster { throw new Error('ES has already been started'); } - await runServerlessCluster(this._log, options); + this._serverlessNodes = await runServerlessCluster(this._log, options); + + if (options.teardown) { + /** + * Ideally would be async and an event like beforeExit or SIGINT, + * but those events are not being triggered in FTR child process. + */ + process.on('exit', () => teardownServerlessClusterSync(this._log, options)); + } } /** diff --git a/packages/kbn-es/src/ess_resources/README.md b/packages/kbn-es/src/ess_resources/README.md new file mode 100644 index 0000000000000..a7af386bcff1f --- /dev/null +++ b/packages/kbn-es/src/ess_resources/README.md @@ -0,0 +1,49 @@ +# Elasticsearch Serverless Resources +The resources in this directory are used for seeding Elasticsearch Serverless (ESS) images with users, roles and tokens for SSL and authentication. ESS requires file realm authentication, so we will bind mount them into the containers at `/usr/share/elasticsearch/config/`. + +## Users + +### Default user + +The default superuser authentication to login to Kibana is: + +``` +username: elastic_serverless +password: changeme +``` + +### Adding users + +1. Add the user:encrypted_password to `users` file. The encrypted password for `elastic_serverless` is `changeme` if you want to reuse the value. +1. Set the new user's roles in `users_roles` file. +1. Add the username to `operator_users.yml` in the array for file realm users. + + +## Service Account and Tokens + +This section for Service Accounts was originally from the [ESS repository](https://github.com/elastic/elasticsearch-serverless/blob/main/serverless-build-tools/src/main/resources/README.service_tokens.md). + +The "service_tokens" file contains this line: +``` +elastic/kibana/kibana-dev:$2a$10$mY2RuGROhk56vLNh.Mgwue98BnkdQPlTR.yGh38ao5jhPJobvuBCq +``` + +That line defines a single service token +- For the `elastic/kibana` service account +- The token is named `kibana-dev` +- The token's secret is hashed using bcrypt (`$2a$`) using `10` rounds + +Although Elasticsearch used PBKDF2_STRETCH by default, the k8s controller +creates tokens using bcrypt, so we mimic that here. + +The hash is not reversible, so this README is here to tell you what the secret is. +The secret value is: `UUUUUULK-* Z4` +That produces an encoded token of: `AAEAAWVsYXN0aWMva2liYW5hL2tpYmFuYS1kZXY6VVVVVVVVTEstKiBaNA` +Yes, the secret was specially chosen to produce an encoded value that can be more easily recognised in development. + +If a node is configured to use this `service_tokens` file, then you can authenticate to it with +``` +curl -H "Authorization: Bearer AAEAAWVsYXN0aWMva2liYW5hL2tpYmFuYS1kZXY6VVVVVVVVTEstKiBaNA" http://localhost:9200/_security/_authenticate +``` + +The name of the token (`kibana-dev`) is important because the `operator_users.yml` file designates that token as an operator and allows us to seed an ESS cluster with this token. \ No newline at end of file diff --git a/packages/kbn-es/src/ess_resources/jwks.json b/packages/kbn-es/src/ess_resources/jwks.json new file mode 100644 index 0000000000000..944705b31416b --- /dev/null +++ b/packages/kbn-es/src/ess_resources/jwks.json @@ -0,0 +1,10 @@ +{ + "keys": [ + { + "kty": "RSA", + "e": "AQAB", + "use": "sig", + "n": "v9-88aGdE4E85PuEycxTA6LkM3TBvNScoeP6A-dd0Myo6-LfBlp1r7BPBWmvi_SC6Zam3U1LE3AekDMwqJg304my0pvh8wOwlmRpgKXDXjvj4s59vdeVNhCB9doIthUABd310o9lyb55fWc_qQYE2LK9AyEjicJswafguH6txV4IwSl13ieZAxni0Ca4CwdzXO1Oi34XjHF8F5x_0puTaQzHn5bPG4fiIJN-pwie0Ba4VEDPO5ca4lLXWVi1bn8xMDTAULrBAXJwDaDdS05KMbc4sPlyQPhtY1gcYvUbozUPYxSWwA7fZgFzV_h-uy_oXf1EXttOxSgog1z3cJzf6Q" + } + ] +} diff --git a/packages/kbn-es/src/ess_resources/operator_users.yml b/packages/kbn-es/src/ess_resources/operator_users.yml new file mode 100644 index 0000000000000..859226f258ebf --- /dev/null +++ b/packages/kbn-es/src/ess_resources/operator_users.yml @@ -0,0 +1,9 @@ +operator: + - usernames: ["elastic_serverless", "system_indices_superuser"] + realm_type: "file" + auth_type: "realm" + - usernames: [ "elastic/kibana" ] + realm_type: "_service_account" + auth_type: "token" + token_source: "file" + token_names: [ "kibana-dev" ] diff --git a/packages/kbn-es/src/ess_resources/role_mapping.yml b/packages/kbn-es/src/ess_resources/role_mapping.yml new file mode 100644 index 0000000000000..882bf8a76fd16 --- /dev/null +++ b/packages/kbn-es/src/ess_resources/role_mapping.yml @@ -0,0 +1,14 @@ +# Role mapping configuration file which has elasticsearch roles as keys +# that map to one or more user or group distinguished names + +#roleA: this is an elasticsearch role +# - groupA-DN this is a group distinguished name +# - groupB-DN +# - user1-DN this is the full user distinguished name + +#power_user: +# - "cn=admins,dc=example,dc=com" +#user: +# - "cn=users,dc=example,dc=com" +# - "cn=admins,dc=example,dc=com" +# - "cn=John Doe,cn=other users,dc=example,dc=com" \ No newline at end of file diff --git a/packages/kbn-es/src/ess_resources/roles.yml b/packages/kbn-es/src/ess_resources/roles.yml new file mode 100644 index 0000000000000..38d3ecfa77d97 --- /dev/null +++ b/packages/kbn-es/src/ess_resources/roles.yml @@ -0,0 +1,791 @@ +system_indices_superuser: + cluster: ['all'] + indices: + - names: ['*'] + privileges: ['all'] + allow_restricted_indices: true + applications: + - application: '*' + privileges: ['*'] + resources: ['*'] + run_as: ['*'] + +# ----- +# Source: https://github.com/elastic/project-controller/blob/main/internal/project/observability/config/roles.yml +# and: https://github.com/elastic/project-controller/blob/main/internal/project/esproject/config/roles.yml +# ----- +viewer: + cluster: [] + indices: + - names: + - "*" + privileges: + - read + - names: + - "/~(([.]|ilm-history-).*)/" + privileges: + - "read" + - "view_index_metadata" + allow_restricted_indices: false + - names: + - ".siem-signals*" + - ".lists-*" + - ".items-*" + privileges: + - "read" + - "view_index_metadata" + allow_restricted_indices: false + - names: + - ".alerts*" + - ".preview.alerts*" + privileges: + - "read" + - "view_index_metadata" + allow_restricted_indices: false + applications: + - application: "kibana-.kibana" + privileges: + - "read" + resources: + - "*" + run_as: [] +editor: + cluster: [] + indices: + - names: + - "/~(([.]|ilm-history-).*)/" + privileges: + - "read" + - "view_index_metadata" + allow_restricted_indices: false + - names: + - "observability-annotations" + privileges: + - "read" + - "view_index_metadata" + - "write" + allow_restricted_indices: false + - names: + - ".siem-signals*" + - ".lists-*" + - ".items-*" + privileges: + - "read" + - "view_index_metadata" + - "write" + - "maintenance" + allow_restricted_indices: false + - names: + - ".internal.alerts*" + - ".alerts*" + - ".internal.preview.alerts*" + - ".preview.alerts*" + privileges: + - "read" + - "view_index_metadata" + - "write" + - "maintenance" + allow_restricted_indices: false + applications: + - application: "kibana-.kibana" + privileges: + - "all" + resources: + - "*" + run_as: [] + +# ----- +# Source: https://github.com/elastic/project-controller/blob/main/internal/project/security/config/roles.yml +# ----- +t1_analyst: + cluster: + indices: + - names: + - ".alerts-security*" + - ".siem-signals-*" + privileges: + - read + - write + - maintenance + - names: + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + - metrics-endpoint.metadata_current_* + - ".fleet-agents*" + - ".fleet-actions*" + privileges: + - read + applications: + - application: ml + privileges: + - read + resources: "*" + - application: siem + privileges: + - read + - read_alerts + - endpoint_list_read + resources: "*" + - application: securitySolutionCases + privileges: + - read + resources: "*" + - application: actions + privileges: + - read + resources: "*" + - application: builtInAlerts + privileges: + - read + resources: "*" + - application: spaces + privileges: + - all + resources: "*" + - application: osquery + privileges: + - read + - run_saved_queries + resources: "*" + +t2_analyst: + cluster: + indices: + - names: + - .alerts-security* + - .siem-signals-* + privileges: + - read + - write + - maintenance + - names: + - .lists* + - .items* + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + - metrics-endpoint.metadata_current_* + - .fleet-agents* + - .fleet-actions* + privileges: + - read + applications: + - application: ml + privileges: + - read + resources: "*" + - application: siem + privileges: + - read + - read_alerts + - endpoint_list_read + resources: "*" + - application: securitySolutionCases + privileges: + - all + resources: "*" + - application: actions + privileges: + - read + resources: "*" + - application: builtInAlerts + privileges: + - read + resources: "*" + - application: spaces + privileges: + - all + resources: "*" + - application: osquery + privileges: + - read + - run_saved_queries + resources: "*" + +t3_analyst: + cluster: + indices: + - names: + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + privileges: + - read + - write + - names: + - .alerts-security* + - .siem-signals-* + privileges: + - read + - write + - names: + - .lists* + - .items* + privileges: + - read + - write + - names: + - metrics-endpoint.metadata_current_* + - .fleet-agents* + - .fleet-actions* + privileges: + - read + applications: + - application: ml + privileges: + - read + resources: "*" + - application: siem + privileges: + - all + - read_alerts + - crud_alerts + - endpoint_list_all + - trusted_applications_all + - event_filters_all + - host_isolation_exceptions_all + - blocklist_all + - policy_management_read # Elastic Defend Policy Management + - host_isolation_all + - process_operations_all + - actions_log_management_all # Response actions history + - file_operations_all + resources: "*" + - application: securitySolutionCases + privileges: + - all + resources: "*" + - application: actions + privileges: + - read + resources: "*" + - application: builtInAlerts + privileges: + - all + resources: "*" + - application: osquery + privileges: + - all + resources: "*" + - application: spaces + privileges: + - all + resources: "*" + +threat_intelligence_analyst: + cluster: + indices: + - names: + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - .lists* + - .items* + - packetbeat-* + - winlogbeat-* + privileges: + - read + - names: + - .alerts-security* + - .siem-signals-* + privileges: + - read + - write + - maintenance + - names: + - metrics-endpoint.metadata_current_* + - .fleet-agents* + - .fleet-actions* + privileges: + - read + applications: + - application: ml + privileges: + - read + resources: "*" + - application: siem + privileges: + - read + - read_alerts + - endpoint_list_read + - blocklist_all + resources: "*" + - application: securitySolutionCases + privileges: + - all + resources: "*" + - application: actions + privileges: + - read + resources: "*" + - application: builtInAlerts + privileges: + - read + resources: "*" + - application: spaces + privileges: + - all + resources: "*" + - application: osquery + privileges: + - all + resources: "*" + +rule_author: + cluster: + indices: + - names: + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + privileges: + - read + - write + - names: + - .alerts-security* + - .siem-signals-* + - .internal.preview.alerts-security* + - .preview.alerts-security* + privileges: + - read + - write + - maintenance + - view_index_metadata + - names: + - .lists* + - .items* + privileges: + - read + - write + - names: + - metrics-endpoint.metadata_current_* + - .fleet-agents* + - .fleet-actions* + privileges: + - read + applications: + - application: ml + privileges: + - read + resources: "*" + - application: siem + privileges: + - all + - read_alerts + - crud_alerts + - policy_management_all + - endpoint_list_all + - trusted_applications_all + - event_filters_all + - host_isolation_exceptions_read + - blocklist_all + - actions_log_management_read + resources: "*" + - application: securitySolutionCases + privileges: + - all + resources: "*" + - application: actions + privileges: + - read + resources: "*" + - application: builtInAlerts + privileges: + - all + resources: "*" + - application: spaces + privileges: + - all + resources: "*" + +soc_manager: + cluster: + indices: + - names: + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + privileges: + - read + - write + - names: + - .alerts-security* + - .siem-signals-* + - .preview.alerts-security* + - .internal.preview.alerts-security* + privileges: + - read + - write + - manage + - names: + - .lists* + - .items* + privileges: + - read + - write + - names: + - metrics-endpoint.metadata_current_* + - .fleet-agents* + - .fleet-actions* + privileges: + - read + applications: + - application: ml + privileges: + - read + resources: "*" + - application: siem + privileges: + - all + - read_alerts + - crud_alerts + - policy_management_all + - endpoint_list_all + - trusted_applications_all + - event_filters_all + - host_isolation_exceptions_all + - blocklist_all + - host_isolation_all + - process_operations_all + - actions_log_management_all + - file_operations_all + - execute_operations_all + resources: "*" + - application: securitySolutionCases + privileges: + - all + resources: "*" + - application: actions + privileges: + - all + resources: "*" + - application: builtInAlerts + privileges: + - all + resources: "*" + - application: spaces + privileges: + - all + resources: "*" + - application: osquery + privileges: + - all + resources: "*" + - application: savedObjectsManagement + privileges: + - all + resources: "*" + +detections_admin: + cluster: + indices: + - names: + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + - .lists* + - .items* + - .alerts-security* + - .siem-signals-* + - .preview.alerts-security* + - .internal.preview.alerts-security* + privileges: + - read + - write + - manage + - names: + - metrics-endpoint.metadata_current_* + - .fleet-agents* + - .fleet-actions* + privileges: + - read + applications: + - application: ml + privileges: + - all + resources: "*" + - application: siem + privileges: + - all + - read_alerts + - crud_alerts + resources: "*" + - application: securitySolutionCases + privileges: + - all + resources: "*" + - application: actions + privileges: + - read + resources: "*" + - application: builtInAlerts + privileges: + - all + resources: "*" + - application: dev_tools + privileges: + - all + resources: "*" + - application: spaces + privileges: + - all + resources: "*" + +platform_engineer: + cluster: + - manage + indices: + - names: + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + - .lists* + - .items* + - .alerts-security* + - .siem-signals-* + - .preview.alerts-security* + - .internal.preview.alerts-security* + privileges: + - all + applications: + - application: ml + privileges: + - all + resources: "*" + - application: siem + privileges: + - all + - read_alerts + - crud_alerts + - policy_management_all + - endpoint_list_all + - trusted_applications_all + - event_filters_all + - host_isolation_exceptions_all + - blocklist_all + - actions_log_management_read + resources: "*" + - application: securitySolutionCases + privileges: + - all + resources: "*" + - application: actions + privileges: + - all + resources: "*" + - application: builtInAlerts + privileges: + - all + resources: "*" + - application: fleet + privileges: + - all + resources: "*" + - application: fleetv2 + privileges: + - all + resources: "*" + - application: spaces + privileges: + - all + resources: "*" + - application: osquery + privileges: + - all + resources: "*" + +endpoint_operations_analyst: + cluster: + indices: + - names: + - metrics-endpoint.metadata_current_* + - .fleet-agents* + - .fleet-actions* + privileges: + - read + - names: + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + - .lists* + - .items* + privileges: + - read + - names: + - .alerts-security* + - .siem-signals-* + - .preview.alerts-security* + - .internal.preview.alerts-security* + privileges: + - read + - write + applications: + - application: ml + privileges: + - read + resources: "*" + - application: siem + privileges: + - all + - read_alerts + - policy_management_all + - endpoint_list_all + - trusted_applications_all + - event_filters_all + - host_isolation_exceptions_all + - blocklist_all + - host_isolation_all + - process_operations_all + - actions_log_management_all # Response History + - file_operations_all + - execute_operations_all # Execute + resources: "*" + - application: securitySolutionCases + privileges: + - all + resources: "*" + - application: actions + privileges: + - all + resources: "*" + - application: builtInAlerts + privileges: + - all + resources: "*" + - application: osquery + privileges: + - all + resources: "*" + - application: fleet + privileges: + - all + resources: "*" + - application: fleetv2 + privileges: + - all + resources: "*" + - application: spaces + privileges: + - all + resources: "*" + +endpoint_policy_manager: + cluster: + indices: + - names: + - metrics-endpoint.metadata_current_* + - .fleet-agents* + - .fleet-actions* + privileges: + - read + - names: + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + - .lists* + - .items* + privileges: + - read + - names: + - .alerts-security* + - .siem-signals-* + - .preview.alerts-security* + - .internal.preview.alerts-security* + privileges: + - read + - write + - manage + applications: + - application: ml + privileges: + - read + resources: "*" + - application: siem + privileges: + - all + - read_alerts + - crud_alerts + - policy_management_all + - trusted_applications_all + - event_filters_all + - host_isolation_exceptions_all + - blocklist_all + - endpoint_list_all + resources: "*" + - application: securitySolutionCases + privileges: + - all + resources: "*" + - application: actions + privileges: + - all + resources: "*" + - application: builtInAlerts + privileges: + - all + resources: "*" + - application: osquery + privileges: + - all + resources: "*" + - application: fleet + privileges: + - all + resources: "*" + - application: fleetv2 + privileges: + - all + resources: "*" + - application: spaces + privileges: + - all + resources: "*" diff --git a/packages/kbn-es/src/ess_resources/secrets.json b/packages/kbn-es/src/ess_resources/secrets.json new file mode 100644 index 0000000000000..ceb7366ee5321 --- /dev/null +++ b/packages/kbn-es/src/ess_resources/secrets.json @@ -0,0 +1,11 @@ +{ + "metadata": { + "version": "1", + "compatibility": "8.11.0" + }, + "string_secrets": { + "xpack.security.http.ssl.keystore.secure_password": "storepass", + "xpack.security.transport.ssl.keystore.secure_password": "storepass", + "xpack.security.authc.realms.jwt.jwt1.client_authentication.shared_secret": "my_super_secret" + } +} \ No newline at end of file diff --git a/packages/kbn-es/src/ess_resources/service_tokens b/packages/kbn-es/src/ess_resources/service_tokens new file mode 100644 index 0000000000000..34bc7476f177f --- /dev/null +++ b/packages/kbn-es/src/ess_resources/service_tokens @@ -0,0 +1 @@ +elastic/kibana/kibana-dev:$2a$10$mY2RuGROhk56vLNh.Mgwue98BnkdQPlTR.yGh38ao5jhPJobvuBCq \ No newline at end of file diff --git a/packages/kbn-es/src/ess_resources/users b/packages/kbn-es/src/ess_resources/users new file mode 100644 index 0000000000000..add4b7325c23d --- /dev/null +++ b/packages/kbn-es/src/ess_resources/users @@ -0,0 +1,2 @@ +elastic_serverless:$2a$10$nN6sRtQl2KX9Gn8kV/.NpOLSk6Jwn8TehEDnZ7aaAgzyl/dy5PYzW +system_indices_superuser:$2a$10$nN6sRtQl2KX9Gn8kV/.NpOLSk6Jwn8TehEDnZ7aaAgzyl/dy5PYzW diff --git a/packages/kbn-es/src/ess_resources/users_roles b/packages/kbn-es/src/ess_resources/users_roles new file mode 100644 index 0000000000000..aa42046898601 --- /dev/null +++ b/packages/kbn-es/src/ess_resources/users_roles @@ -0,0 +1,2 @@ +superuser:elastic_serverless +system_indices_superuser:system_indices_superuser diff --git a/packages/kbn-es/src/paths.ts b/packages/kbn-es/src/paths.ts index 1d909f523302e..76cf4271c7ce8 100644 --- a/packages/kbn-es/src/paths.ts +++ b/packages/kbn-es/src/paths.ts @@ -7,7 +7,7 @@ */ import Os from 'os'; -import Path from 'path'; +import { resolve } from 'path'; function maybeUseBat(bin: string) { return Os.platform().startsWith('win') ? `${bin}.bat` : bin; @@ -15,7 +15,7 @@ function maybeUseBat(bin: string) { const tempDir = Os.tmpdir(); -export const BASE_PATH = Path.resolve(tempDir, 'kbn-es'); +export const BASE_PATH = resolve(tempDir, 'kbn-es'); export const GRADLE_BIN = maybeUseBat('./gradlew'); export const ES_BIN = maybeUseBat('bin/elasticsearch'); @@ -23,3 +23,30 @@ export const ES_PLUGIN_BIN = maybeUseBat('bin/elasticsearch-plugin'); export const ES_CONFIG = 'config/elasticsearch.yml'; export const ES_KEYSTORE_BIN = maybeUseBat('./bin/elasticsearch-keystore'); + +export const ESS_OPERATOR_USERS_PATH = resolve(__dirname, './ess_resources/operator_users.yml'); +export const ESS_SERVICE_TOKENS_PATH = resolve(__dirname, './ess_resources/service_tokens'); + +export const ESS_USERS_PATH = resolve(__dirname, './ess_resources/users'); +export const ESS_USERS_ROLES_PATH = resolve(__dirname, './ess_resources/users_roles'); + +export const ESS_ROLES_PATH = resolve(__dirname, './ess_resources/roles.yml'); +export const ESS_ROLE_MAPPING_PATH = resolve(__dirname, './ess_resources/role_mapping.yml'); + +export const ESS_SECRETS_PATH = resolve(__dirname, './ess_resources/secrets.json'); + +export const ESS_JWKS_PATH = resolve(__dirname, './ess_resources/jwks.json'); + +export const ESS_RESOURCES_PATHS = [ + ESS_OPERATOR_USERS_PATH, + ESS_ROLE_MAPPING_PATH, + ESS_ROLES_PATH, + ESS_SERVICE_TOKENS_PATH, + ESS_USERS_PATH, + ESS_USERS_ROLES_PATH, +]; + +export const ESS_CONFIG_PATH = '/usr/share/elasticsearch/config/'; + +// Files need to be inside config for permissions reasons inside the container +export const ESS_FILES_PATH = `${ESS_CONFIG_PATH}files/`; diff --git a/packages/kbn-es/src/utils/docker.test.ts b/packages/kbn-es/src/utils/docker.test.ts index ef978fe76c409..35696e1f91af8 100644 --- a/packages/kbn-es/src/utils/docker.test.ts +++ b/packages/kbn-es/src/utils/docker.test.ts @@ -12,21 +12,33 @@ import { stat } from 'fs/promises'; import { DOCKER_IMG, + detectRunningNodes, maybeCreateDockerNetwork, + maybePullDockerImage, resolveDockerCmd, resolveDockerImage, resolveEsArgs, + resolvePort, runDockerContainer, runServerlessCluster, runServerlessEsNode, SERVERLESS_IMG, setupServerlessVolumes, + stopServerlessCluster, + teardownServerlessClusterSync, verifyDockerInstalled, } from './docker'; import { ToolingLog, ToolingLogCollectingWriter } from '@kbn/tooling-log'; +import { ES_P12_PATH } from '@kbn/dev-utils'; +import { ESS_RESOURCES_PATHS } from '../paths'; jest.mock('execa'); const execa = jest.requireMock('execa'); +jest.mock('@elastic/elasticsearch', () => { + return { + Client: jest.fn(), + }; +}); const log = new ToolingLog(); const logWriter = new ToolingLogCollectingWriter(); @@ -62,7 +74,7 @@ const volumeCmdTest = async (volumeCmd: string[]) => { // extract only permission from mode // eslint-disable-next-line no-bitwise - expect((await stat(serverlessObjectStorePath)).mode & 0o777).toBe(0o766); + expect((await stat(serverlessObjectStorePath)).mode & 0o777).toBe(0o777); }; describe('resolveDockerImage()', () => { @@ -103,6 +115,32 @@ describe('resolveDockerImage()', () => { }); }); +describe('resolvePort()', () => { + test('should return default port when no options', () => { + const port = resolvePort({}); + + expect(port).toMatchInlineSnapshot(` + Array [ + "-p", + "127.0.0.1:9200:9200", + ] + `); + }); + + test('should return custom port when passed in options', () => { + const port = resolvePort({ port: 9220 }); + + expect(port).toMatchInlineSnapshot(` + Array [ + "-p", + "127.0.0.1:9220:9220", + "--env", + "http.port=9220", + ] + `); + }); +}); + describe('verifyDockerInstalled()', () => { test('should call the correct Docker command and log the version', async () => { execa.mockImplementationOnce(() => Promise.resolve({ stdout: 'Docker Version 123' })); @@ -190,6 +228,55 @@ describe('maybeCreateDockerNetwork()', () => { }); }); +describe('maybePullDockerImage()', () => { + test('should pull the passed image', async () => { + execa.mockImplementationOnce(() => Promise.resolve({ exitCode: 0 })); + + await maybePullDockerImage(log, DOCKER_IMG); + + expect(execa.mock.calls[0][0]).toEqual('docker'); + expect(execa.mock.calls[0][1]).toEqual(expect.arrayContaining(['pull', DOCKER_IMG])); + }); +}); + +describe('detectRunningNodes()', () => { + const nodes = ['es01', 'es02', 'es03']; + + test('should not error if no nodes detected', async () => { + execa.mockImplementationOnce(() => Promise.resolve({ stdout: '' })); + + await detectRunningNodes(log, {}); + + expect(execa.mock.calls).toHaveLength(1); + expect(execa.mock.calls[0][1]).toEqual(expect.arrayContaining(['ps', '--quiet', '--filter'])); + }); + + test('should kill nodes if detected and kill passed', async () => { + execa.mockImplementationOnce(() => + Promise.resolve({ + stdout: nodes.join('\n'), + }) + ); + + await detectRunningNodes(log, { kill: true }); + + expect(execa.mock.calls).toHaveLength(2); + expect(execa.mock.calls[1][1]).toEqual(expect.arrayContaining(nodes.concat('kill'))); + }); + + test('should error if nodes detected and kill not passed', async () => { + execa.mockImplementationOnce(() => + Promise.resolve({ + stdout: nodes.join('\n'), + }) + ); + + await expect(detectRunningNodes(log, {})).rejects.toThrowErrorMatchingInlineSnapshot( + `"ES has already been started, pass --kill to automatically stop the nodes on startup."` + ); + }); +}); + describe('resolveEsArgs()', () => { const defaultEsArgs: Array<[string, string]> = [ ['foo', 'bar'], @@ -253,6 +340,39 @@ describe('resolveEsArgs()', () => { ] `); }); + + test('should add SSL args and enable security when SSL is passed', () => { + const esArgs = resolveEsArgs([...defaultEsArgs, ['xpack.security.enabled', 'false']], { + ssl: true, + }); + + expect(esArgs).toHaveLength(20); + expect(esArgs).not.toEqual(expect.arrayContaining(['xpack.security.enabled=false'])); + expect(esArgs).toMatchInlineSnapshot(` + Array [ + "--env", + "foo=bar", + "--env", + "qux=zip", + "--env", + "xpack.security.enabled=true", + "--env", + "xpack.security.http.ssl.enabled=true", + "--env", + "xpack.security.http.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elasticsearch.p12", + "--env", + "xpack.security.http.ssl.verification_mode=certificate", + "--env", + "xpack.security.transport.ssl.enabled=true", + "--env", + "xpack.security.transport.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elasticsearch.p12", + "--env", + "xpack.security.transport.ssl.verification_mode=certificate", + "--env", + "xpack.security.operator_privileges.enabled=true", + ] + `); + }); }); describe('setupServerlessVolumes()', () => { @@ -292,6 +412,20 @@ describe('setupServerlessVolumes()', () => { volumeCmdTest(volumeCmd); expect(existsSync(`${serverlessObjectStorePath}/cluster_state/lease`)).toBe(false); }); + + test('should add SSL volumes when ssl is passed', async () => { + mockFs(existingObjectStore); + + const volumeCmd = await setupServerlessVolumes(log, { basePath: baseEsPath, ssl: true }); + + const requiredPaths = [`${baseEsPath}:/objectstore:z`, ES_P12_PATH, ...ESS_RESOURCES_PATHS]; + const pathsNotIncludedInCmd = requiredPaths.filter( + (path) => !volumeCmd.some((cmd) => cmd.includes(path)) + ); + + expect(volumeCmd).toHaveLength(20); + expect(pathsNotIncludedInCmd).toEqual([]); + }); }); describe('runServerlessEsNode()', () => { @@ -333,8 +467,65 @@ describe('runServerlessCluster()', () => { await runServerlessCluster(log, { basePath: baseEsPath }); - // Verify Docker and network then run three nodes - expect(execa.mock.calls).toHaveLength(5); + // setupDocker execa calls then run three nodes and attach logger + expect(execa.mock.calls).toHaveLength(8); + }); + describe('waitForReady', () => { + test('should wait for serverless nodes to be ready to serve requests', async () => { + mockFs({ + [baseEsPath]: {}, + }); + execa.mockImplementation(() => Promise.resolve({ stdout: '' })); + const info = jest.fn(); + jest.requireMock('@elastic/elasticsearch').Client.mockImplementation(() => ({ info })); + + info.mockImplementationOnce(() => Promise.reject()); // first call fails + info.mockImplementationOnce(() => Promise.resolve()); // then succeeds + + await runServerlessCluster(log, { basePath: baseEsPath, waitForReady: true }); + expect(info).toHaveBeenCalledTimes(2); + }); + }); +}); + +describe('stopServerlessCluster()', () => { + test('should stop passed in nodes', async () => { + const nodes = ['es01', 'es02', 'es03']; + execa.mockImplementation(() => Promise.resolve({ stdout: '' })); + + await stopServerlessCluster(log, nodes); + + expect(execa.mock.calls[0][0]).toEqual('docker'); + expect(execa.mock.calls[0][1]).toEqual( + expect.arrayContaining(['container', 'stop'].concat(nodes)) + ); + }); +}); + +describe('teardownServerlessClusterSync()', () => { + const defaultOptions = { basePath: 'foo/bar' }; + + test('should kill running serverless nodes', () => { + const nodes = ['es01', 'es02', 'es03']; + execa.commandSync.mockImplementation(() => ({ + stdout: nodes.join('\n'), + })); + + teardownServerlessClusterSync(log, defaultOptions); + + expect(execa.commandSync.mock.calls).toHaveLength(2); + expect(execa.commandSync.mock.calls[0][0]).toEqual(expect.stringContaining(SERVERLESS_IMG)); + expect(execa.commandSync.mock.calls[1][0]).toEqual(`docker kill ${nodes.join(' ')}`); + }); + + test('should not kill if no serverless nodes', () => { + execa.commandSync.mockImplementation(() => ({ + stdout: '\n', + })); + + teardownServerlessClusterSync(log, defaultOptions); + + expect(execa.commandSync.mock.calls).toHaveLength(1); }); }); @@ -364,7 +555,7 @@ describe('runDockerContainer()', () => { execa.mockImplementation(() => Promise.resolve({ stdout: '' })); await expect(runDockerContainer(log, {})).resolves.toEqual({ stdout: '' }); - // Verify Docker and network then run container - expect(execa.mock.calls).toHaveLength(3); + // setupDocker execa calls then run container + expect(execa.mock.calls).toHaveLength(5); }); }); diff --git a/packages/kbn-es/src/utils/docker.ts b/packages/kbn-es/src/utils/docker.ts index 6552545e10a3e..01db89a14c6ab 100644 --- a/packages/kbn-es/src/utils/docker.ts +++ b/packages/kbn-es/src/utils/docker.ts @@ -9,17 +9,36 @@ import chalk from 'chalk'; import execa from 'execa'; import fs from 'fs'; import Fsp from 'fs/promises'; -import { resolve } from 'path'; +import { resolve, basename, join } from 'path'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/tooling-log'; -import { kibanaPackageJson as pkg } from '@kbn/repo-info'; +import { kibanaPackageJson as pkg, REPO_ROOT } from '@kbn/repo-info'; +import { ES_P12_PASSWORD, ES_P12_PATH } from '@kbn/dev-utils'; import { createCliError } from '../errors'; import { EsClusterExecOptions } from '../cluster_exec_options'; +import { + ESS_RESOURCES_PATHS, + ESS_SECRETS_PATH, + ESS_JWKS_PATH, + ESS_CONFIG_PATH, + ESS_FILES_PATH, +} from '../paths'; +import { + ELASTIC_SERVERLESS_SUPERUSER, + ELASTIC_SERVERLESS_SUPERUSER_PASSWORD, +} from './ess_file_realm'; +import { SYSTEM_INDICES_SUPERUSER } from './native_realm'; interface BaseOptions { tag?: string; image?: string; + port?: number; + ssl?: boolean; + /** Kill running cluster before starting a new cluster */ + kill?: boolean; + files?: string | string[]; } export interface DockerOptions extends EsClusterExecOptions, BaseOptions { @@ -27,8 +46,16 @@ export interface DockerOptions extends EsClusterExecOptions, BaseOptions { } export interface ServerlessOptions extends EsClusterExecOptions, BaseOptions { + /** Clean (or delete) all data created by the ES cluster after it is stopped */ clean?: boolean; + /** Path to the directory where the ES cluster will store data */ basePath: string; + /** If this process exits, teardown the ES cluster as well */ + teardown?: boolean; + /** Start the ES cluster in the background instead of remaining attached: useful for running tests */ + background?: boolean; + /** Wait for the ES cluster to be ready to serve requests */ + waitForReady?: boolean; } interface ServerlessEsNodeArgs { @@ -38,6 +65,7 @@ interface ServerlessEsNodeArgs { params: string[]; } +export const DEFAULT_PORT = 9200; const DOCKER_REGISTRY = 'docker.elastic.co'; const DOCKER_BASE_CMD = [ @@ -53,9 +81,6 @@ const DOCKER_BASE_CMD = [ '--name', 'es01', - '-p', - '127.0.0.1:9200:9200', - '-p', '127.0.0.1:9300:9300', ]; @@ -78,6 +103,8 @@ export const SERVERLESS_REPO = `${DOCKER_REGISTRY}/elasticsearch-ci/elasticsearc export const SERVERLESS_TAG = 'latest'; export const SERVERLESS_IMG = `${SERVERLESS_REPO}:${SERVERLESS_TAG}`; +// See for default cluster settings +// https://github.com/elastic/elasticsearch-serverless/blob/main/serverless-build-tools/src/main/kotlin/elasticsearch.serverless-run.gradle.kts const SHARED_SERVERLESS_PARAMS = [ 'run', @@ -85,9 +112,16 @@ const SHARED_SERVERLESS_PARAMS = [ '--detach', + '--interactive', + + '--tty', + '--net', 'elastic', + '--env', + 'path.repo=/objectstore', + '--env', 'cluster.initial_master_nodes=es01,es02,es03', @@ -99,27 +133,65 @@ const SHARED_SERVERLESS_PARAMS = [ '--env', 'stateless.object_store.bucket=stateless', - - '--env', - 'path.repo=/objectstore', ]; // only allow certain ES args to be overwrote by options const DEFAULT_SERVERLESS_ESARGS: Array<[string, string]> = [ ['ES_JAVA_OPTS', '-Xms1g -Xmx1g'], - ['xpack.security.enabled', 'false'], + ['ES_LOG_STYLE', 'file'], ['cluster.name', 'stateless'], + + ['ingest.geoip.downloader.enabled', 'false'], + + ['xpack.ml.enabled', 'true'], + + ['xpack.security.enabled', 'false'], +]; + +const DEFAULT_SSL_ESARGS: Array<[string, string]> = [ + ['xpack.security.enabled', 'true'], + + ['xpack.security.http.ssl.enabled', 'true'], + + ['xpack.security.http.ssl.keystore.path', `${ESS_CONFIG_PATH}certs/elasticsearch.p12`], + + ['xpack.security.http.ssl.verification_mode', 'certificate'], + + ['xpack.security.transport.ssl.enabled', 'true'], + + ['xpack.security.transport.ssl.keystore.path', `${ESS_CONFIG_PATH}certs/elasticsearch.p12`], + + ['xpack.security.transport.ssl.verification_mode', 'certificate'], + + ['xpack.security.operator_privileges.enabled', 'true'], +]; + +const SERVERLESS_SSL_ESARGS: Array<[string, string]> = [ + ['xpack.security.authc.realms.jwt.jwt1.client_authentication.type', 'shared_secret'], + + ['xpack.security.authc.realms.jwt.jwt1.order', '-98'], + + ['xpack.security.authc.realms.jwt.jwt1.allowed_issuer', 'https://kibana.elastic.co/jwt/'], + + ['xpack.security.authc.realms.jwt.jwt1.allowed_audiences', 'elasticsearch'], + + ['xpack.security.authc.realms.jwt.jwt1.pkc_jwkset_path', `${ESS_CONFIG_PATH}secrets/jwks.json`], + + ['xpack.security.authc.realms.jwt.jwt1.claims.principal', 'sub'], +]; + +const DOCKER_SSL_ESARGS: Array<[string, string]> = [ + ['xpack.security.http.ssl.keystore.password', ES_P12_PASSWORD], + + ['xpack.security.transport.ssl.keystore.password', ES_P12_PASSWORD], ]; const SERVERLESS_NODES: Array> = [ { name: 'es01', params: [ - '-p', - '127.0.0.1:9200:9200', - '-p', '127.0.0.1:9300:9300', @@ -127,9 +199,13 @@ const SERVERLESS_NODES: Array> = [ 'discovery.seed_hosts=es02,es03', '--env', - 'node.roles=["master","index"]', + 'node.roles=["master","remote_cluster_client","ingest","index"]', + ], + esArgs: [ + ['xpack.searchable.snapshot.shared_cache.size', '16MB'], + + ['xpack.searchable.snapshot.shared_cache.region_size', '256K'], ], - esArgs: [['xpack.searchable.snapshot.shared_cache.size', '1gb']], }, { name: 'es02', @@ -144,9 +220,13 @@ const SERVERLESS_NODES: Array> = [ 'discovery.seed_hosts=es01,es03', '--env', - 'node.roles=["master","search"]', + 'node.roles=["master","remote_cluster_client","search"]', + ], + esArgs: [ + ['xpack.searchable.snapshot.shared_cache.size', '16MB'], + + ['xpack.searchable.snapshot.shared_cache.region_size', '256K'], ], - esArgs: [['xpack.searchable.snapshot.shared_cache.size', '1gb']], }, { name: 'es03', @@ -161,7 +241,7 @@ const SERVERLESS_NODES: Array> = [ 'discovery.seed_hosts=es01,es02', '--env', - 'node.roles=["master"]', + 'node.roles=["master","remote_cluster_client","ml","transform"]', ], }, ]; @@ -190,6 +270,22 @@ export function resolveDockerImage({ return defaultImg; } +/** + * Determine the port to bind the Serverless index node or Docker node to + */ +export function resolvePort(options: ServerlessOptions | DockerOptions) { + if (options.port) { + return [ + '-p', + `127.0.0.1:${options.port}:${options.port}`, + '--env', + `http.port=${options.port}`, + ]; + } + + return ['-p', `127.0.0.1:${DEFAULT_PORT}:${DEFAULT_PORT}`]; +} + /** * Verify that Docker is installed locally */ @@ -227,12 +323,70 @@ export async function maybeCreateDockerNetwork(log: ToolingLog) { log.indent(-4); } +/** + * + * Pull a Docker image if needed. Ensures latest image. + * Stops serverless from pulling the same image in each node's promise and + * gives better control of log output, instead of falling back to docker run. + */ +export async function maybePullDockerImage(log: ToolingLog, image: string) { + log.info(chalk.bold(`Checking for image: ${image}`)); + + await execa('docker', ['pull', image], { + // inherit is required to show Docker pull output + stdio: ['ignore', 'inherit', 'pipe'], + }).catch(({ message, stderr }) => { + throw createCliError( + stderr.includes('unauthorized: authentication required') + ? `Error authenticating with ${DOCKER_REGISTRY}. Visit https://docker-auth.elastic.co/github_auth to login.` + : message + ); + }); +} + +export async function detectRunningNodes( + log: ToolingLog, + options: ServerlessOptions | DockerOptions +) { + const namesCmd = SERVERLESS_NODES.reduce((acc, { name }) => { + acc.push('--filter', `name=${name}`); + + return acc; + }, []); + + const { stdout } = await execa('docker', ['ps', '--quiet'].concat(namesCmd)); + const runningNodes = stdout.split(/\r?\n/).filter((s) => s); + + if (runningNodes.length) { + if (options.kill) { + log.info(chalk.bold('Killing running ES Nodes.')); + await execa('docker', ['kill'].concat(runningNodes)); + + return; + } + + throw createCliError( + 'ES has already been started, pass --kill to automatically stop the nodes on startup.' + ); + } +} + /** * Common setup for Docker and Serverless containers */ -async function setupDocker(log: ToolingLog) { +async function setupDocker({ + log, + image, + options, +}: { + log: ToolingLog; + image: string; + options: ServerlessOptions | DockerOptions; +}) { await verifyDockerInstalled(log); + await detectRunningNodes(log, options); await maybeCreateDockerNetwork(log); + await maybePullDockerImage(log, image); } /** @@ -242,40 +396,69 @@ export function resolveEsArgs( defaultEsArgs: Array<[string, string]>, options: ServerlessOptions | DockerOptions ) { + const { esArgs: customEsArgs, password, ssl } = options; const esArgs = new Map(defaultEsArgs); - if (options.esArgs) { - const args = typeof options.esArgs === 'string' ? [options.esArgs] : options.esArgs; + if (ssl) { + DEFAULT_SSL_ESARGS.forEach((arg) => { + esArgs.set(arg[0], arg[1]); + }); + } + + if (customEsArgs) { + const args = typeof customEsArgs === 'string' ? [customEsArgs] : customEsArgs; args.forEach((arg) => { const [key, ...value] = arg.split('='); + + // Guide the user to use SSL flag instead of manual setup + if (key === 'xpack.security.enabled' && value?.[0] === 'true') { + throw createCliError( + 'Use the --ssl flag to automatically enable and set up the security plugin.' + ); + } + esArgs.set(key.trim(), value.join('=').trim()); }); } - if (options.password) { - esArgs.set('ELASTIC_PASSWORD', options.password); + if (password) { + esArgs.set('ELASTIC_PASSWORD', password); } return Array.from(esArgs).flatMap((e) => ['--env', e.join('=')]); } +function getESp12Volume() { + return ['--volume', `${ES_P12_PATH}:${ESS_CONFIG_PATH}certs/elasticsearch.p12`]; +} + +/** + * Removes REPO_ROOT from hostPath. Keep the rest to avoid filename collisions. + * Returns the path where a file will be mounted inside the ES or ESS container. + * /root/kibana/package/foo/bar.json => /usr/share/elasticsearch/files/package/foo/bar.json + */ +export function getDockerFileMountPath(hostPath: string) { + return join(ESS_FILES_PATH, hostPath.replace(REPO_ROOT, '')); +} + /** * Setup local volumes for Serverless ES */ export async function setupServerlessVolumes(log: ToolingLog, options: ServerlessOptions) { - const volumePath = resolve(options.basePath, 'stateless'); + const { basePath, clean, ssl, files } = options; + const objectStorePath = resolve(basePath, 'stateless'); - log.info(chalk.bold(`Checking for local Serverless ES object store at ${volumePath}`)); + log.info(chalk.bold(`Checking for local serverless ES object store at ${objectStorePath}`)); log.indent(4); - if (options.clean && fs.existsSync(volumePath)) { + if (clean && fs.existsSync(objectStorePath)) { log.info('Cleaning existing object store.'); - await Fsp.rm(volumePath, { recursive: true, force: true }); + await Fsp.rm(objectStorePath, { recursive: true, force: true }); } - if (options.clean || !fs.existsSync(volumePath)) { - await Fsp.mkdir(volumePath, { recursive: true }).then(() => + if (clean || !fs.existsSync(objectStorePath)) { + await Fsp.mkdir(objectStorePath, { recursive: true }).then(() => log.info('Created new object store.') ); } else { @@ -283,13 +466,45 @@ export async function setupServerlessVolumes(log: ToolingLog, options: Serverles } // Permissions are set separately from mkdir due to default umask - await Fsp.chmod(volumePath, 0o766).then(() => - log.info('Setup object store permissions (chmod 766).') - ); + await Fsp.chmod(objectStorePath, 0o777).then(() => { + log.info('Setup object store permissions (chmod 777).'); + }); log.indent(-4); - return ['--volume', `${options.basePath}:/objectstore:z`]; + const volumeCmds = ['--volume', `${basePath}:/objectstore:z`]; + + if (files) { + const _files = typeof files === 'string' ? [files] : files; + const fileCmds = _files.reduce((acc, filePath) => { + acc.push('--volume', `${filePath}:${getDockerFileMountPath(filePath)}:z`); + + return acc; + }, []); + + volumeCmds.push(...fileCmds); + } + + if (ssl) { + const essResources = ESS_RESOURCES_PATHS.reduce((acc, path) => { + acc.push('--volume', `${path}:${ESS_CONFIG_PATH}${basename(path)}`); + + return acc; + }, []); + + volumeCmds.push( + ...getESp12Volume(), + ...essResources, + + '--volume', + `${ESS_SECRETS_PATH}:${ESS_CONFIG_PATH}secrets/secrets.json:z`, + + '--volume', + `${ESS_JWKS_PATH}:${ESS_CONFIG_PATH}secrets/jwks.json:z` + ); + } + + return volumeCmds; } /** @@ -316,7 +531,7 @@ export async function runServerlessEsNode( image ); - log.info(chalk.bold(`Running Serverless ES node: ${name}`)); + log.info(chalk.bold(`Running serverless ES node: ${name}`)); log.indent(4, () => log.info(chalk.dim(`docker ${dockerCmd.join(' ')}`))); const { stdout } = await execa('docker', dockerCmd); @@ -332,22 +547,53 @@ export async function runServerlessEsNode( ); } +function getESClient( + { node }: { node: string } = { node: `http://localhost:${DEFAULT_PORT}` } +): Client { + return new Client({ + node, + Connection: HttpConnection, + }); +} + +const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); +async function waitUntilClusterReady(timeoutMs = 60 * 1000): Promise { + const started = Date.now(); + const client = getESClient(); + while (started + timeoutMs > Date.now()) { + try { + await client.info(); + break; + } catch (e) { + await delay(1000); + /* trap to continue */ + } + } +} + /** * Runs an ES Serverless Cluster through Docker */ export async function runServerlessCluster(log: ToolingLog, options: ServerlessOptions) { - await setupDocker(log); + const image = getServerlessImage(options); + await setupDocker({ log, image, options }); const volumeCmd = await setupServerlessVolumes(log, options); - const image = getServerlessImage(options); const nodeNames = await Promise.all( - SERVERLESS_NODES.map(async (node) => { + SERVERLESS_NODES.map(async (node, i) => { await runServerlessEsNode(log, { ...node, image, params: node.params.concat( - resolveEsArgs(DEFAULT_SERVERLESS_ESARGS.concat(node.esArgs ?? []), options), + resolveEsArgs( + DEFAULT_SERVERLESS_ESARGS.concat( + node.esArgs ?? [], + options.ssl ? SERVERLESS_SSL_ESARGS : [] + ), + options + ), + i === 0 ? resolvePort(options) : [], volumeCmd ), }); @@ -358,6 +604,62 @@ export async function runServerlessCluster(log: ToolingLog, options: ServerlessO log.success(`Serverless ES cluster running. Stop the cluster: ${chalk.bold(`docker container stop ${nodeNames.join(' ')}`)} `); + + if (options.ssl) { + log.success(`SSL and Security have been enabled for ES. + Login through your browser with username ${chalk.bold.cyan( + ELASTIC_SERVERLESS_SUPERUSER + )} or ${chalk.bold.cyan(SYSTEM_INDICES_SUPERUSER)} and password ${chalk.bold.magenta( + ELASTIC_SERVERLESS_SUPERUSER_PASSWORD + )}. + `); + + log.warning(`Kibana should be started with the SSL flag so that it can authenticate with ES. + See packages/kbn-es/src/ess_resources/README.md for additional information on authentication. + `); + } + + if (options.waitForReady) { + log.info('Waiting until ES is ready to serve requests...'); + await waitUntilClusterReady(); + log.success('ES is ready'); + } + + if (!options.background) { + // The ESS cluster has to be started detached, so we attach a logger afterwards for output + await execa('docker', ['logs', '-f', SERVERLESS_NODES[0].name], { + // inherit is required to show Docker output and Java console output for pw, enrollment token, etc + stdio: ['ignore', 'inherit', 'inherit'], + }); + } + + return nodeNames; +} + +/** + * Stop a serverless ES cluster by node names + */ +export async function stopServerlessCluster(log: ToolingLog, nodes: string[]) { + log.info('Stopping serverless ES cluster.'); + + await execa('docker', ['container', 'stop'].concat(nodes)); +} + +/** + * Kill any serverless ES nodes which are running. + */ +export function teardownServerlessClusterSync(log: ToolingLog, options: ServerlessOptions) { + const { stdout } = execa.commandSync( + `docker ps --filter status=running --filter ancestor=${getServerlessImage(options)} --quiet` + ); + // Filter empty strings + const runningNodes = stdout.split(/\r?\n/).filter((s) => s); + + if (runningNodes.length) { + log.info('Killing running serverless ES nodes.'); + + execa.commandSync(`docker kill ${runningNodes.join(' ')}`); + } } /** @@ -370,29 +672,35 @@ function getDockerImage(options: DockerOptions) { /** * Resolve the full command to run Elasticsearch Docker container */ -export function resolveDockerCmd(options: DockerOptions) { +export function resolveDockerCmd(options: DockerOptions, image: string = DOCKER_IMG) { if (options.dockerCmd) { return options.dockerCmd.split(' '); } return DOCKER_BASE_CMD.concat( - resolveEsArgs(DEFAULT_DOCKER_ESARGS, options), - getDockerImage(options) + resolveEsArgs(DEFAULT_DOCKER_ESARGS.concat(options.ssl ? DOCKER_SSL_ESARGS : []), options), + resolvePort(options), + options.ssl ? getESp12Volume() : [], + image ); } /** - * * Runs an Elasticsearch Docker Container */ export async function runDockerContainer(log: ToolingLog, options: DockerOptions) { - await setupDocker(log); + let image; + + if (!options.dockerCmd) { + image = getDockerImage(options); + await setupDocker({ log, image, options }); + } - const dockerCmd = resolveDockerCmd(options); + const dockerCmd = resolveDockerCmd(options, image); log.info(chalk.dim(`docker ${dockerCmd.join(' ')}`)); return await execa('docker', dockerCmd, { - // inherit is required to show Docker pull output and Java console output for pw, enrollment token, etc + // inherit is required to show Docker output and Java console output for pw, enrollment token, etc stdio: ['ignore', 'inherit', 'inherit'], }); } diff --git a/packages/kbn-es/src/utils/ess_file_realm.ts b/packages/kbn-es/src/utils/ess_file_realm.ts new file mode 100644 index 0000000000000..6b7745ac9351a --- /dev/null +++ b/packages/kbn-es/src/utils/ess_file_realm.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 const ELASTIC_SERVERLESS_SUPERUSER = 'elastic_serverless'; +export const ELASTIC_SERVERLESS_SUPERUSER_PASSWORD = 'changeme'; diff --git a/packages/kbn-es/src/utils/index.ts b/packages/kbn-es/src/utils/index.ts index 25591a786603c..cc46d0bf28271 100644 --- a/packages/kbn-es/src/utils/index.ts +++ b/packages/kbn-es/src/utils/index.ts @@ -17,3 +17,4 @@ export { buildSnapshot } from './build_snapshot'; export { archiveForPlatform } from './build_snapshot'; export * from './parse_timeout_to_ms'; export * from './docker'; +export * from './ess_file_realm'; diff --git a/packages/kbn-eslint-plugin-imports/src/rules/no_unused_imports.ts b/packages/kbn-eslint-plugin-imports/src/rules/no_unused_imports.ts index f12e149af9f66..5818bef672faf 100644 --- a/packages/kbn-eslint-plugin-imports/src/rules/no_unused_imports.ts +++ b/packages/kbn-eslint-plugin-imports/src/rules/no_unused_imports.ts @@ -78,6 +78,7 @@ function isTsOrEslintIgnore(comment: Comment) { export const NoUnusedImportsRule: Rule.RuleModule = { meta: { + hasSuggestions: true, fixable: 'code', docs: { url: 'https://github.com/elastic/kibana/blob/main/packages/kbn-eslint-plugin-imports/README.mdx#kbnimportsno_unused_imports', diff --git a/packages/kbn-event-annotation-components/components/annotation_editor_controls/tooltip_annotation_panel.tsx b/packages/kbn-event-annotation-components/components/annotation_editor_controls/tooltip_annotation_panel.tsx index f1ed8ccc7ccb2..e4f3e7f976d1c 100644 --- a/packages/kbn-event-annotation-components/components/annotation_editor_controls/tooltip_annotation_panel.tsx +++ b/packages/kbn-event-annotation-components/components/annotation_editor_controls/tooltip_annotation_panel.tsx @@ -9,7 +9,7 @@ import { htmlIdGenerator, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useCallback, useMemo } from 'react'; -import { useExistingFieldsReader } from '@kbn/unified-field-list/src/hooks/use_existing_fields'; +import { useExistingFieldsReader, getFieldIconType } from '@kbn/unified-field-list'; import { FieldOption, FieldOptionValue, @@ -139,7 +139,7 @@ export function TooltipSection({ value: { type: 'field', field: field.name, - dataType: field.type, + dataType: getFieldIconType(field), }, exists: dataView.id ? hasFieldData(dataView.id, field.name) : false, compatible: true, diff --git a/packages/kbn-expandable-flyout/src/components/left_section.tsx b/packages/kbn-expandable-flyout/src/components/left_section.tsx index 88326acb6476e..25958fbb332b7 100644 --- a/packages/kbn-expandable-flyout/src/components/left_section.tsx +++ b/packages/kbn-expandable-flyout/src/components/left_section.tsx @@ -7,7 +7,7 @@ */ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import React from 'react'; +import React, { useMemo } from 'react'; import { LEFT_SECTION } from './test_ids'; interface LeftSectionProps { @@ -25,8 +25,12 @@ interface LeftSectionProps { * Left section of the expanded flyout rendering a panel */ export const LeftSection: React.FC = ({ component, width }: LeftSectionProps) => { + const style = useMemo( + () => ({ height: '100%', width: `${width * 100}%`, overflowY: 'scroll' }), + [width] + ); return ( - + {component} ); diff --git a/packages/kbn-expandable-flyout/src/components/right_section.tsx b/packages/kbn-expandable-flyout/src/components/right_section.tsx index 027f523a93050..b6020a54bc39f 100644 --- a/packages/kbn-expandable-flyout/src/components/right_section.tsx +++ b/packages/kbn-expandable-flyout/src/components/right_section.tsx @@ -7,7 +7,7 @@ */ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import React from 'react'; +import React, { useMemo } from 'react'; import { RIGHT_SECTION } from './test_ids'; interface RightSectionProps { @@ -28,12 +28,13 @@ export const RightSection: React.FC = ({ component, width, }: RightSectionProps) => { + const style = useMemo( + () => ({ height: '100%', width: `${width * 100}%`, overflowY: 'scroll' }), + [width] + ); + return ( - + {component} ); diff --git a/packages/kbn-expandable-flyout/src/index.tsx b/packages/kbn-expandable-flyout/src/index.tsx index e6e5af85ac0a3..d5a1bff46439b 100644 --- a/packages/kbn-expandable-flyout/src/index.tsx +++ b/packages/kbn-expandable-flyout/src/index.tsx @@ -7,7 +7,6 @@ */ import React, { useCallback, useMemo } from 'react'; -import { css } from '@emotion/react'; import type { EuiFlyoutProps } from '@elastic/eui'; import { EuiFlexGroup, EuiFlyout } from '@elastic/eui'; import { useExpandableFlyoutContext } from './context'; @@ -28,10 +27,6 @@ export interface ExpandableFlyoutProps extends Omit { handleOnFlyoutClosed?: () => void; } -const flyoutStyles = css` - overflow-y: scroll; -`; - const flyoutInnerStyles = { height: '100%' }; /** @@ -88,13 +83,7 @@ export const ExpandableFlyout: React.FC = ({ const previewSectionWidth: number = leftSection ? 0.4 : 1; return ( - + kv.split('=')) + ); + + // Update labels before start for consistency b/w APM services + await this.updateTelemetryAndAPMLabels(journeyLabels); + this.apm = apmNode.start({ serviceName: 'functional test runner', environment: process.env.CI ? 'ci' : 'development', diff --git a/packages/kbn-journeys/services/page/kibana_page.ts b/packages/kbn-journeys/services/page/kibana_page.ts index b53a5f91a9e45..72e595601473a 100644 --- a/packages/kbn-journeys/services/page/kibana_page.ts +++ b/packages/kbn-journeys/services/page/kibana_page.ts @@ -72,4 +72,18 @@ export class KibanaPage { checkAttribute: 'data-ech-render-complete', }); } + + async clearInput(locator: string) { + const textArea = this.page.locator(locator); + await textArea.clear(); + } + + async clickAndWaitFor( + locator: string, + state?: 'attached' | 'detached' | 'visible' | 'hidden' | undefined + ) { + const element = this.page.locator(locator); + await element.click(); + await element.waitFor({ state }); + } } diff --git a/packages/kbn-journeys/tsconfig.json b/packages/kbn-journeys/tsconfig.json index d52e0f32586af..7917081cb1847 100644 --- a/packages/kbn-journeys/tsconfig.json +++ b/packages/kbn-journeys/tsconfig.json @@ -18,6 +18,7 @@ "@kbn/repo-info", "@kbn/std", "@kbn/test-subj-selector", + "@kbn/core-http-common", ], "exclude": [ "target/**/*", diff --git a/packages/kbn-monaco/src/esql/antlr/.gitignore b/packages/kbn-monaco/src/esql/antlr/.gitignore new file mode 100644 index 0000000000000..f7754e5f01083 --- /dev/null +++ b/packages/kbn-monaco/src/esql/antlr/.gitignore @@ -0,0 +1 @@ +.antlr/* \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 b/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 index 49d73416712a8..b5688e0915a33 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 @@ -7,15 +7,23 @@ lexer grammar esql_lexer; -EVAL : 'eval' -> pushMode(EXPRESSION); -EXPLAIN : 'explain' -> pushMode(EXPRESSION); -FROM : 'from' -> pushMode(SOURCE_IDENTIFIERS); -ROW : 'row' -> pushMode(EXPRESSION); -STATS : 'stats' -> pushMode(EXPRESSION); -WHERE : 'where' -> pushMode(EXPRESSION); -SORT : 'sort' -> pushMode(EXPRESSION); -LIMIT : 'limit' -> pushMode(EXPRESSION); -PROJECT : 'project' -> pushMode(SOURCE_IDENTIFIERS); +DISSECT : D I S S E C T -> pushMode(EXPRESSION); +GROK : G R O K -> pushMode(EXPRESSION); +EVAL : E V A L -> pushMode(EXPRESSION); +EXPLAIN : E X P L A I N -> pushMode(EXPLAIN_MODE); +FROM : F R O M -> pushMode(SOURCE_IDENTIFIERS); +ROW : R O W -> pushMode(EXPRESSION); +STATS : S T A T S -> pushMode(EXPRESSION); +WHERE : W H E R E -> pushMode(EXPRESSION); +SORT : S O R T -> pushMode(EXPRESSION); +MV_EXPAND : M V UNDERSCORE E X P A N D -> pushMode(EXPRESSION); +LIMIT : L I M I T -> pushMode(EXPRESSION); +PROJECT : P R O J E C T -> pushMode(EXPRESSION); +DROP : D R O P -> pushMode(EXPRESSION); +RENAME : R E N A M E -> pushMode(EXPRESSION); +SHOW : S H O W -> pushMode(EXPRESSION); +ENRICH : E N R I C H -> pushMode(ENRICH_IDENTIFIERS); +KEEP : K E E P -> pushMode(EXPRESSION); LINE_COMMENT : '//' ~[\r\n]* '\r'? '\n'? -> channel(HIDDEN) @@ -28,7 +36,12 @@ MULTILINE_COMMENT WS : [ \r\n\t]+ -> channel(HIDDEN) ; - +mode EXPLAIN_MODE; +EXPLAIN_OPENING_BRACKET : '[' -> type(OPENING_BRACKET), pushMode(DEFAULT_MODE); +EXPLAIN_PIPE : '|' -> type(PIPE), popMode; +EXPLAIN_WS : WS -> channel(HIDDEN); +EXPLAIN_LINE_COMMENT : LINE_COMMENT -> channel(HIDDEN); +EXPLAIN_MULTILINE_COMMENT : MULTILINE_COMMENT -> channel(HIDDEN); mode EXPRESSION; PIPE : '|' -> popMode; @@ -71,17 +84,34 @@ DECIMAL_LITERAL BY : 'by'; +DATE_LITERAL + : 'year' + | 'month' + | 'day' + | 'second' + | 'minute' + | 'hour' + ; + AND : 'and'; ASSIGN : '='; COMMA : ','; DOT : '.'; LP : '('; -OPENING_BRACKET : '[' -> pushMode(DEFAULT_MODE); -CLOSING_BRACKET : ']' -> popMode, popMode; // pop twice, once to clear mode of current cmd and once to exit DEFAULT_MODE -NOT : 'not'; -NULL : 'null'; +OPENING_BRACKET : '[' -> pushMode(EXPRESSION), pushMode(EXPRESSION); +CLOSING_BRACKET : ']' -> popMode, popMode; +NOT : N O T; +LIKE: L I K E; +RLIKE: R L I K E; +IN: I N; +IS: I S; +AS: A S; +NULL : N U L L; OR : 'or'; RP : ')'; +UNDERSCORE: '_'; +INFO : 'info'; +FUNCTIONS : 'functions'; BOOLEAN_VALUE : 'true' @@ -102,6 +132,7 @@ MINUS : '-'; ASTERISK : '*'; SLASH : '/'; PERCENT : '%'; +TEN: '10'; ORDERING : 'asc' @@ -114,16 +145,74 @@ NULLS_ORDERING_DIRECTION | 'last' ; +MATH_FUNCTION + : R O U N D + | A B S + | P O W + | L O G TEN + | P I + | T A U + | E + | S U B S T R I N G + | T R I M + | C O N C A T + | S T A R T S UNDERSCORE W I T H + | D A T E UNDERSCORE F O R M A T + | D A T E UNDERSCORE T R U N C + | D A T E UNDERSCORE P A R S E + | A U T O UNDERSCORE B U C K E T + | I S UNDERSCORE F I N I T E + | I S UNDERSCORE I N F I N I T E + | C A S E + | L E N G T H + | M V UNDERSCORE M A X + | M V UNDERSCORE M I N + | M V UNDERSCORE A V G + | M V UNDERSCORE S U M + | M V UNDERSCORE C O U N T + | M V UNDERSCORE C O N C A T + | M V UNDERSCORE J O I N + | M V UNDERSCORE M E D I A N + | M V UNDERSCORE D E D U P E + | M E T A D A T A + | S P L I T + | T O UNDERSCORE S T R I N G + | T O UNDERSCORE S T R + | T O UNDERSCORE B O O L + | T O UNDERSCORE B O O L E A N + | T O UNDERSCORE D A T E T I M E + | T O UNDERSCORE D T + | T O UNDERSCORE D B L + | T O UNDERSCORE D O U B L E + | T O UNDERSCORE I N T + | T O UNDERSCORE I N T E G E R + | T O UNDERSCORE L O N G + | T O UNDERSCORE I P + | T O UNDERSCORE V E R S I O N + | T O UNDERSCORE U N S I G N E D UNDERSCORE L O N G + ; + UNARY_FUNCTION - : 'round' - | 'avg' - | 'min' - | 'max' - | 'sum' + : A V G + | M I N + | M A X + | S U M + | C O U N T + | C O U N T UNDERSCORE D I S T I N C T + | P E R C E N T I L E + | M E D I A N + | M E D I A N UNDERSCORE A B S O L U T E UNDERSCORE D E V I A T I O N + ; + +WHERE_FUNCTIONS + : C I D R UNDERSCORE M A T C H ; UNQUOTED_IDENTIFIER - : (LETTER | '_') (LETTER | DIGIT | '_')* + : LETTER (LETTER | DIGIT | '_' | ASTERISK)* + // only allow @ at beginning of identifier to keep the option to allow @ as infix operator in the future + // also, single `_` and `@` characters are not valid identifiers + | ('_' | '@') (LETTER | DIGIT | '_' | ASTERISK)+ ; QUOTED_IDENTIFIER @@ -146,9 +235,11 @@ EXPR_WS mode SOURCE_IDENTIFIERS; SRC_PIPE : '|' -> type(PIPE), popMode; +SRC_OPENING_BRACKET : '[' -> type(OPENING_BRACKET), pushMode(SOURCE_IDENTIFIERS), pushMode(SOURCE_IDENTIFIERS); SRC_CLOSING_BRACKET : ']' -> popMode, popMode, type(CLOSING_BRACKET); SRC_COMMA : ',' -> type(COMMA); SRC_ASSIGN : '=' -> type(ASSIGN); +METADATA: M E T A D A T A; SRC_UNQUOTED_IDENTIFIER : SRC_UNQUOTED_IDENTIFIER_PART+ @@ -174,3 +265,65 @@ SRC_MULTILINE_COMMENT SRC_WS : WS -> channel(HIDDEN) ; + +mode ENRICH_IDENTIFIERS; + +ON : O N; +WITH : W I T H; + +ENR_PIPE : '|' -> type(PIPE), popMode; +ENR_CLOSING_BRACKET : ']' -> popMode, popMode, type(CLOSING_BRACKET); +ENR_COMMA : ',' -> type(COMMA); +ENR_ASSIGN : '=' -> type(ASSIGN); + +ENR_UNQUOTED_IDENTIFIER + : ENR_UNQUOTED_IDENTIFIER_PART+ + ; + +fragment ENR_UNQUOTED_IDENTIFIER_PART + : ~[=`|,[\]/ \t\r\n]+ + | '/' ~[*/] // allow single / but not followed by another / or * which would start a comment + ; + +ENR_QUOTED_IDENTIFIER + : QUOTED_IDENTIFIER + ; + +ENR_LINE_COMMENT + : LINE_COMMENT -> channel(HIDDEN) + ; + +ENR_MULTILINE_COMMENT + : MULTILINE_COMMENT -> channel(HIDDEN) + ; + +ENR_WS + : WS -> channel(HIDDEN) + ; + +fragment A : [aA]; // match either an 'a' or 'A' +fragment B : [bB]; +fragment C : [cC]; +fragment D : [dD]; +fragment E : [eE]; +fragment F : [fF]; +fragment G : [gG]; +fragment H : [hH]; +fragment I : [iI]; +fragment J : [jJ]; +fragment K : [kK]; +fragment L : [lL]; +fragment M : [mM]; +fragment N : [nN]; +fragment O : [oO]; +fragment P : [pP]; +fragment Q : [qQ]; +fragment R : [rR]; +fragment S : [sS]; +fragment T : [tT]; +fragment U : [uU]; +fragment V : [vV]; +fragment W : [wW]; +fragment X : [xX]; +fragment Y : [yY]; +fragment Z : [zZ]; \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp b/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp index a7fee84591c3b..394ed7fc4ee63 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp @@ -1,14 +1,25 @@ token literal names: null -'eval' -'explain' -'from' -'row' -'stats' -'where' -'sort' -'limit' -'project' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null null null null @@ -17,17 +28,26 @@ null null null 'by' +null 'and' null null '.' '(' -'[' +null ']' -'not' -'null' +null +null +null +null +null +null +null 'or' ')' +'_' +'info' +'functions' null null '+' @@ -35,6 +55,7 @@ null '*' '/' '%' +'10' null 'nulls' null @@ -49,9 +70,22 @@ null null null null +null +null +null +null +null +null +null +null +null +null +null token symbolic names: null +DISSECT +GROK EVAL EXPLAIN FROM @@ -59,16 +93,26 @@ ROW STATS WHERE SORT +MV_EXPAND LIMIT PROJECT +DROP +RENAME +SHOW +ENRICH +KEEP LINE_COMMENT MULTILINE_COMMENT WS +EXPLAIN_WS +EXPLAIN_LINE_COMMENT +EXPLAIN_MULTILINE_COMMENT PIPE STRING INTEGER_LITERAL DECIMAL_LITERAL BY +DATE_LITERAL AND ASSIGN COMMA @@ -77,9 +121,17 @@ LP OPENING_BRACKET CLOSING_BRACKET NOT +LIKE +RLIKE +IN +IS +AS NULL OR RP +UNDERSCORE +INFO +FUNCTIONS BOOLEAN_VALUE COMPARISON_OPERATOR PLUS @@ -87,22 +139,36 @@ MINUS ASTERISK SLASH PERCENT +TEN ORDERING NULLS_ORDERING NULLS_ORDERING_DIRECTION +MATH_FUNCTION UNARY_FUNCTION +WHERE_FUNCTIONS UNQUOTED_IDENTIFIER QUOTED_IDENTIFIER EXPR_LINE_COMMENT EXPR_MULTILINE_COMMENT EXPR_WS +METADATA SRC_UNQUOTED_IDENTIFIER SRC_QUOTED_IDENTIFIER SRC_LINE_COMMENT SRC_MULTILINE_COMMENT SRC_WS +ON +WITH +ENR_UNQUOTED_IDENTIFIER +ENR_QUOTED_IDENTIFIER +ENR_LINE_COMMENT +ENR_MULTILINE_COMMENT +ENR_WS +EXPLAIN_PIPE rule names: +DISSECT +GROK EVAL EXPLAIN FROM @@ -110,11 +176,22 @@ ROW STATS WHERE SORT +MV_EXPAND LIMIT PROJECT +DROP +RENAME +SHOW +ENRICH +KEEP LINE_COMMENT MULTILINE_COMMENT WS +EXPLAIN_OPENING_BRACKET +EXPLAIN_PIPE +EXPLAIN_WS +EXPLAIN_LINE_COMMENT +EXPLAIN_MULTILINE_COMMENT PIPE DIGIT LETTER @@ -125,6 +202,7 @@ STRING INTEGER_LITERAL DECIMAL_LITERAL BY +DATE_LITERAL AND ASSIGN COMMA @@ -133,9 +211,17 @@ LP OPENING_BRACKET CLOSING_BRACKET NOT +LIKE +RLIKE +IN +IS +AS NULL OR RP +UNDERSCORE +INFO +FUNCTIONS BOOLEAN_VALUE COMPARISON_OPERATOR PLUS @@ -143,25 +229,68 @@ MINUS ASTERISK SLASH PERCENT +TEN ORDERING NULLS_ORDERING NULLS_ORDERING_DIRECTION +MATH_FUNCTION UNARY_FUNCTION +WHERE_FUNCTIONS UNQUOTED_IDENTIFIER QUOTED_IDENTIFIER EXPR_LINE_COMMENT EXPR_MULTILINE_COMMENT EXPR_WS SRC_PIPE +SRC_OPENING_BRACKET SRC_CLOSING_BRACKET SRC_COMMA SRC_ASSIGN +METADATA SRC_UNQUOTED_IDENTIFIER SRC_UNQUOTED_IDENTIFIER_PART SRC_QUOTED_IDENTIFIER SRC_LINE_COMMENT SRC_MULTILINE_COMMENT SRC_WS +ON +WITH +ENR_PIPE +ENR_CLOSING_BRACKET +ENR_COMMA +ENR_ASSIGN +ENR_UNQUOTED_IDENTIFIER +ENR_UNQUOTED_IDENTIFIER_PART +ENR_QUOTED_IDENTIFIER +ENR_LINE_COMMENT +ENR_MULTILINE_COMMENT +ENR_WS +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y +Z channel names: DEFAULT_TOKEN_CHANNEL @@ -169,8 +298,10 @@ HIDDEN mode names: DEFAULT_MODE +EXPLAIN_MODE EXPRESSION SOURCE_IDENTIFIERS +ENRICH_IDENTIFIERS atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 51, 533, 8, 1, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 7, 11, 199, 10, 11, 12, 11, 14, 11, 202, 11, 11, 3, 11, 5, 11, 205, 10, 11, 3, 11, 5, 11, 208, 10, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 7, 12, 217, 10, 12, 12, 12, 14, 12, 220, 11, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 6, 13, 228, 10, 13, 13, 13, 14, 13, 229, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 5, 19, 249, 10, 19, 3, 19, 6, 19, 252, 10, 19, 13, 19, 14, 19, 253, 3, 20, 3, 20, 3, 20, 7, 20, 259, 10, 20, 12, 20, 14, 20, 262, 11, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 7, 20, 270, 10, 20, 12, 20, 14, 20, 273, 11, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 5, 20, 280, 10, 20, 3, 20, 5, 20, 283, 10, 20, 5, 20, 285, 10, 20, 3, 21, 6, 21, 288, 10, 21, 13, 21, 14, 21, 289, 3, 22, 6, 22, 293, 10, 22, 13, 22, 14, 22, 294, 3, 22, 3, 22, 7, 22, 299, 10, 22, 12, 22, 14, 22, 302, 11, 22, 3, 22, 3, 22, 6, 22, 306, 10, 22, 13, 22, 14, 22, 307, 3, 22, 6, 22, 311, 10, 22, 13, 22, 14, 22, 312, 3, 22, 3, 22, 7, 22, 317, 10, 22, 12, 22, 14, 22, 320, 11, 22, 5, 22, 322, 10, 22, 3, 22, 3, 22, 3, 22, 3, 22, 6, 22, 328, 10, 22, 13, 22, 14, 22, 329, 3, 22, 3, 22, 5, 22, 334, 10, 22, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 5, 35, 383, 10, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 5, 36, 395, 10, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 5, 42, 414, 10, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 5, 44, 431, 10, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 5, 45, 450, 10, 45, 3, 46, 3, 46, 5, 46, 454, 10, 46, 3, 46, 3, 46, 3, 46, 7, 46, 459, 10, 46, 12, 46, 14, 46, 462, 11, 46, 3, 47, 3, 47, 3, 47, 3, 47, 7, 47, 468, 10, 47, 12, 47, 14, 47, 471, 11, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 54, 3, 54, 3, 54, 3, 54, 3, 55, 6, 55, 507, 10, 55, 13, 55, 14, 55, 508, 3, 56, 6, 56, 512, 10, 56, 13, 56, 14, 56, 513, 3, 56, 3, 56, 5, 56, 518, 10, 56, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 4, 218, 271, 2, 2, 61, 5, 2, 3, 7, 2, 4, 9, 2, 5, 11, 2, 6, 13, 2, 7, 15, 2, 8, 17, 2, 9, 19, 2, 10, 21, 2, 11, 23, 2, 12, 25, 2, 13, 27, 2, 14, 29, 2, 15, 31, 2, 2, 33, 2, 2, 35, 2, 2, 37, 2, 2, 39, 2, 2, 41, 2, 16, 43, 2, 17, 45, 2, 18, 47, 2, 19, 49, 2, 20, 51, 2, 21, 53, 2, 22, 55, 2, 23, 57, 2, 24, 59, 2, 25, 61, 2, 26, 63, 2, 27, 65, 2, 28, 67, 2, 29, 69, 2, 30, 71, 2, 31, 73, 2, 32, 75, 2, 33, 77, 2, 34, 79, 2, 35, 81, 2, 36, 83, 2, 37, 85, 2, 38, 87, 2, 39, 89, 2, 40, 91, 2, 41, 93, 2, 42, 95, 2, 43, 97, 2, 44, 99, 2, 45, 101, 2, 46, 103, 2, 2, 105, 2, 2, 107, 2, 2, 109, 2, 2, 111, 2, 47, 113, 2, 2, 115, 2, 48, 117, 2, 49, 119, 2, 50, 121, 2, 51, 5, 2, 3, 4, 13, 4, 2, 12, 12, 15, 15, 5, 2, 11, 12, 15, 15, 34, 34, 3, 2, 50, 59, 4, 2, 67, 92, 99, 124, 7, 2, 36, 36, 94, 94, 112, 112, 116, 116, 118, 118, 6, 2, 12, 12, 15, 15, 36, 36, 94, 94, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 3, 2, 98, 98, 12, 2, 11, 12, 15, 15, 34, 34, 46, 46, 49, 49, 63, 63, 93, 93, 95, 95, 98, 98, 126, 126, 4, 2, 44, 44, 49, 49, 2, 570, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 3, 29, 3, 2, 2, 2, 3, 41, 3, 2, 2, 2, 3, 43, 3, 2, 2, 2, 3, 45, 3, 2, 2, 2, 3, 47, 3, 2, 2, 2, 3, 49, 3, 2, 2, 2, 3, 51, 3, 2, 2, 2, 3, 53, 3, 2, 2, 2, 3, 55, 3, 2, 2, 2, 3, 57, 3, 2, 2, 2, 3, 59, 3, 2, 2, 2, 3, 61, 3, 2, 2, 2, 3, 63, 3, 2, 2, 2, 3, 65, 3, 2, 2, 2, 3, 67, 3, 2, 2, 2, 3, 69, 3, 2, 2, 2, 3, 71, 3, 2, 2, 2, 3, 73, 3, 2, 2, 2, 3, 75, 3, 2, 2, 2, 3, 77, 3, 2, 2, 2, 3, 79, 3, 2, 2, 2, 3, 81, 3, 2, 2, 2, 3, 83, 3, 2, 2, 2, 3, 85, 3, 2, 2, 2, 3, 87, 3, 2, 2, 2, 3, 89, 3, 2, 2, 2, 3, 91, 3, 2, 2, 2, 3, 93, 3, 2, 2, 2, 3, 95, 3, 2, 2, 2, 3, 97, 3, 2, 2, 2, 3, 99, 3, 2, 2, 2, 3, 101, 3, 2, 2, 2, 4, 103, 3, 2, 2, 2, 4, 105, 3, 2, 2, 2, 4, 107, 3, 2, 2, 2, 4, 109, 3, 2, 2, 2, 4, 111, 3, 2, 2, 2, 4, 115, 3, 2, 2, 2, 4, 117, 3, 2, 2, 2, 4, 119, 3, 2, 2, 2, 4, 121, 3, 2, 2, 2, 5, 123, 3, 2, 2, 2, 7, 130, 3, 2, 2, 2, 9, 140, 3, 2, 2, 2, 11, 147, 3, 2, 2, 2, 13, 153, 3, 2, 2, 2, 15, 161, 3, 2, 2, 2, 17, 169, 3, 2, 2, 2, 19, 176, 3, 2, 2, 2, 21, 184, 3, 2, 2, 2, 23, 194, 3, 2, 2, 2, 25, 211, 3, 2, 2, 2, 27, 227, 3, 2, 2, 2, 29, 233, 3, 2, 2, 2, 31, 237, 3, 2, 2, 2, 33, 239, 3, 2, 2, 2, 35, 241, 3, 2, 2, 2, 37, 244, 3, 2, 2, 2, 39, 246, 3, 2, 2, 2, 41, 284, 3, 2, 2, 2, 43, 287, 3, 2, 2, 2, 45, 333, 3, 2, 2, 2, 47, 335, 3, 2, 2, 2, 49, 338, 3, 2, 2, 2, 51, 342, 3, 2, 2, 2, 53, 344, 3, 2, 2, 2, 55, 346, 3, 2, 2, 2, 57, 348, 3, 2, 2, 2, 59, 350, 3, 2, 2, 2, 61, 354, 3, 2, 2, 2, 63, 359, 3, 2, 2, 2, 65, 363, 3, 2, 2, 2, 67, 368, 3, 2, 2, 2, 69, 371, 3, 2, 2, 2, 71, 382, 3, 2, 2, 2, 73, 394, 3, 2, 2, 2, 75, 396, 3, 2, 2, 2, 77, 398, 3, 2, 2, 2, 79, 400, 3, 2, 2, 2, 81, 402, 3, 2, 2, 2, 83, 404, 3, 2, 2, 2, 85, 413, 3, 2, 2, 2, 87, 415, 3, 2, 2, 2, 89, 430, 3, 2, 2, 2, 91, 449, 3, 2, 2, 2, 93, 453, 3, 2, 2, 2, 95, 463, 3, 2, 2, 2, 97, 474, 3, 2, 2, 2, 99, 478, 3, 2, 2, 2, 101, 482, 3, 2, 2, 2, 103, 486, 3, 2, 2, 2, 105, 491, 3, 2, 2, 2, 107, 497, 3, 2, 2, 2, 109, 501, 3, 2, 2, 2, 111, 506, 3, 2, 2, 2, 113, 517, 3, 2, 2, 2, 115, 519, 3, 2, 2, 2, 117, 521, 3, 2, 2, 2, 119, 525, 3, 2, 2, 2, 121, 529, 3, 2, 2, 2, 123, 124, 7, 103, 2, 2, 124, 125, 7, 120, 2, 2, 125, 126, 7, 99, 2, 2, 126, 127, 7, 110, 2, 2, 127, 128, 3, 2, 2, 2, 128, 129, 8, 2, 2, 2, 129, 6, 3, 2, 2, 2, 130, 131, 7, 103, 2, 2, 131, 132, 7, 122, 2, 2, 132, 133, 7, 114, 2, 2, 133, 134, 7, 110, 2, 2, 134, 135, 7, 99, 2, 2, 135, 136, 7, 107, 2, 2, 136, 137, 7, 112, 2, 2, 137, 138, 3, 2, 2, 2, 138, 139, 8, 3, 2, 2, 139, 8, 3, 2, 2, 2, 140, 141, 7, 104, 2, 2, 141, 142, 7, 116, 2, 2, 142, 143, 7, 113, 2, 2, 143, 144, 7, 111, 2, 2, 144, 145, 3, 2, 2, 2, 145, 146, 8, 4, 3, 2, 146, 10, 3, 2, 2, 2, 147, 148, 7, 116, 2, 2, 148, 149, 7, 113, 2, 2, 149, 150, 7, 121, 2, 2, 150, 151, 3, 2, 2, 2, 151, 152, 8, 5, 2, 2, 152, 12, 3, 2, 2, 2, 153, 154, 7, 117, 2, 2, 154, 155, 7, 118, 2, 2, 155, 156, 7, 99, 2, 2, 156, 157, 7, 118, 2, 2, 157, 158, 7, 117, 2, 2, 158, 159, 3, 2, 2, 2, 159, 160, 8, 6, 2, 2, 160, 14, 3, 2, 2, 2, 161, 162, 7, 121, 2, 2, 162, 163, 7, 106, 2, 2, 163, 164, 7, 103, 2, 2, 164, 165, 7, 116, 2, 2, 165, 166, 7, 103, 2, 2, 166, 167, 3, 2, 2, 2, 167, 168, 8, 7, 2, 2, 168, 16, 3, 2, 2, 2, 169, 170, 7, 117, 2, 2, 170, 171, 7, 113, 2, 2, 171, 172, 7, 116, 2, 2, 172, 173, 7, 118, 2, 2, 173, 174, 3, 2, 2, 2, 174, 175, 8, 8, 2, 2, 175, 18, 3, 2, 2, 2, 176, 177, 7, 110, 2, 2, 177, 178, 7, 107, 2, 2, 178, 179, 7, 111, 2, 2, 179, 180, 7, 107, 2, 2, 180, 181, 7, 118, 2, 2, 181, 182, 3, 2, 2, 2, 182, 183, 8, 9, 2, 2, 183, 20, 3, 2, 2, 2, 184, 185, 7, 114, 2, 2, 185, 186, 7, 116, 2, 2, 186, 187, 7, 113, 2, 2, 187, 188, 7, 108, 2, 2, 188, 189, 7, 103, 2, 2, 189, 190, 7, 101, 2, 2, 190, 191, 7, 118, 2, 2, 191, 192, 3, 2, 2, 2, 192, 193, 8, 10, 3, 2, 193, 22, 3, 2, 2, 2, 194, 195, 7, 49, 2, 2, 195, 196, 7, 49, 2, 2, 196, 200, 3, 2, 2, 2, 197, 199, 10, 2, 2, 2, 198, 197, 3, 2, 2, 2, 199, 202, 3, 2, 2, 2, 200, 198, 3, 2, 2, 2, 200, 201, 3, 2, 2, 2, 201, 204, 3, 2, 2, 2, 202, 200, 3, 2, 2, 2, 203, 205, 7, 15, 2, 2, 204, 203, 3, 2, 2, 2, 204, 205, 3, 2, 2, 2, 205, 207, 3, 2, 2, 2, 206, 208, 7, 12, 2, 2, 207, 206, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 209, 3, 2, 2, 2, 209, 210, 8, 11, 4, 2, 210, 24, 3, 2, 2, 2, 211, 212, 7, 49, 2, 2, 212, 213, 7, 44, 2, 2, 213, 218, 3, 2, 2, 2, 214, 217, 5, 25, 12, 2, 215, 217, 11, 2, 2, 2, 216, 214, 3, 2, 2, 2, 216, 215, 3, 2, 2, 2, 217, 220, 3, 2, 2, 2, 218, 219, 3, 2, 2, 2, 218, 216, 3, 2, 2, 2, 219, 221, 3, 2, 2, 2, 220, 218, 3, 2, 2, 2, 221, 222, 7, 44, 2, 2, 222, 223, 7, 49, 2, 2, 223, 224, 3, 2, 2, 2, 224, 225, 8, 12, 4, 2, 225, 26, 3, 2, 2, 2, 226, 228, 9, 3, 2, 2, 227, 226, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 227, 3, 2, 2, 2, 229, 230, 3, 2, 2, 2, 230, 231, 3, 2, 2, 2, 231, 232, 8, 13, 4, 2, 232, 28, 3, 2, 2, 2, 233, 234, 7, 126, 2, 2, 234, 235, 3, 2, 2, 2, 235, 236, 8, 14, 5, 2, 236, 30, 3, 2, 2, 2, 237, 238, 9, 4, 2, 2, 238, 32, 3, 2, 2, 2, 239, 240, 9, 5, 2, 2, 240, 34, 3, 2, 2, 2, 241, 242, 7, 94, 2, 2, 242, 243, 9, 6, 2, 2, 243, 36, 3, 2, 2, 2, 244, 245, 10, 7, 2, 2, 245, 38, 3, 2, 2, 2, 246, 248, 9, 8, 2, 2, 247, 249, 9, 9, 2, 2, 248, 247, 3, 2, 2, 2, 248, 249, 3, 2, 2, 2, 249, 251, 3, 2, 2, 2, 250, 252, 5, 31, 15, 2, 251, 250, 3, 2, 2, 2, 252, 253, 3, 2, 2, 2, 253, 251, 3, 2, 2, 2, 253, 254, 3, 2, 2, 2, 254, 40, 3, 2, 2, 2, 255, 260, 7, 36, 2, 2, 256, 259, 5, 35, 17, 2, 257, 259, 5, 37, 18, 2, 258, 256, 3, 2, 2, 2, 258, 257, 3, 2, 2, 2, 259, 262, 3, 2, 2, 2, 260, 258, 3, 2, 2, 2, 260, 261, 3, 2, 2, 2, 261, 263, 3, 2, 2, 2, 262, 260, 3, 2, 2, 2, 263, 285, 7, 36, 2, 2, 264, 265, 7, 36, 2, 2, 265, 266, 7, 36, 2, 2, 266, 267, 7, 36, 2, 2, 267, 271, 3, 2, 2, 2, 268, 270, 10, 2, 2, 2, 269, 268, 3, 2, 2, 2, 270, 273, 3, 2, 2, 2, 271, 272, 3, 2, 2, 2, 271, 269, 3, 2, 2, 2, 272, 274, 3, 2, 2, 2, 273, 271, 3, 2, 2, 2, 274, 275, 7, 36, 2, 2, 275, 276, 7, 36, 2, 2, 276, 277, 7, 36, 2, 2, 277, 279, 3, 2, 2, 2, 278, 280, 7, 36, 2, 2, 279, 278, 3, 2, 2, 2, 279, 280, 3, 2, 2, 2, 280, 282, 3, 2, 2, 2, 281, 283, 7, 36, 2, 2, 282, 281, 3, 2, 2, 2, 282, 283, 3, 2, 2, 2, 283, 285, 3, 2, 2, 2, 284, 255, 3, 2, 2, 2, 284, 264, 3, 2, 2, 2, 285, 42, 3, 2, 2, 2, 286, 288, 5, 31, 15, 2, 287, 286, 3, 2, 2, 2, 288, 289, 3, 2, 2, 2, 289, 287, 3, 2, 2, 2, 289, 290, 3, 2, 2, 2, 290, 44, 3, 2, 2, 2, 291, 293, 5, 31, 15, 2, 292, 291, 3, 2, 2, 2, 293, 294, 3, 2, 2, 2, 294, 292, 3, 2, 2, 2, 294, 295, 3, 2, 2, 2, 295, 296, 3, 2, 2, 2, 296, 300, 5, 55, 27, 2, 297, 299, 5, 31, 15, 2, 298, 297, 3, 2, 2, 2, 299, 302, 3, 2, 2, 2, 300, 298, 3, 2, 2, 2, 300, 301, 3, 2, 2, 2, 301, 334, 3, 2, 2, 2, 302, 300, 3, 2, 2, 2, 303, 305, 5, 55, 27, 2, 304, 306, 5, 31, 15, 2, 305, 304, 3, 2, 2, 2, 306, 307, 3, 2, 2, 2, 307, 305, 3, 2, 2, 2, 307, 308, 3, 2, 2, 2, 308, 334, 3, 2, 2, 2, 309, 311, 5, 31, 15, 2, 310, 309, 3, 2, 2, 2, 311, 312, 3, 2, 2, 2, 312, 310, 3, 2, 2, 2, 312, 313, 3, 2, 2, 2, 313, 321, 3, 2, 2, 2, 314, 318, 5, 55, 27, 2, 315, 317, 5, 31, 15, 2, 316, 315, 3, 2, 2, 2, 317, 320, 3, 2, 2, 2, 318, 316, 3, 2, 2, 2, 318, 319, 3, 2, 2, 2, 319, 322, 3, 2, 2, 2, 320, 318, 3, 2, 2, 2, 321, 314, 3, 2, 2, 2, 321, 322, 3, 2, 2, 2, 322, 323, 3, 2, 2, 2, 323, 324, 5, 39, 19, 2, 324, 334, 3, 2, 2, 2, 325, 327, 5, 55, 27, 2, 326, 328, 5, 31, 15, 2, 327, 326, 3, 2, 2, 2, 328, 329, 3, 2, 2, 2, 329, 327, 3, 2, 2, 2, 329, 330, 3, 2, 2, 2, 330, 331, 3, 2, 2, 2, 331, 332, 5, 39, 19, 2, 332, 334, 3, 2, 2, 2, 333, 292, 3, 2, 2, 2, 333, 303, 3, 2, 2, 2, 333, 310, 3, 2, 2, 2, 333, 325, 3, 2, 2, 2, 334, 46, 3, 2, 2, 2, 335, 336, 7, 100, 2, 2, 336, 337, 7, 123, 2, 2, 337, 48, 3, 2, 2, 2, 338, 339, 7, 99, 2, 2, 339, 340, 7, 112, 2, 2, 340, 341, 7, 102, 2, 2, 341, 50, 3, 2, 2, 2, 342, 343, 7, 63, 2, 2, 343, 52, 3, 2, 2, 2, 344, 345, 7, 46, 2, 2, 345, 54, 3, 2, 2, 2, 346, 347, 7, 48, 2, 2, 347, 56, 3, 2, 2, 2, 348, 349, 7, 42, 2, 2, 349, 58, 3, 2, 2, 2, 350, 351, 7, 93, 2, 2, 351, 352, 3, 2, 2, 2, 352, 353, 8, 29, 6, 2, 353, 60, 3, 2, 2, 2, 354, 355, 7, 95, 2, 2, 355, 356, 3, 2, 2, 2, 356, 357, 8, 30, 5, 2, 357, 358, 8, 30, 5, 2, 358, 62, 3, 2, 2, 2, 359, 360, 7, 112, 2, 2, 360, 361, 7, 113, 2, 2, 361, 362, 7, 118, 2, 2, 362, 64, 3, 2, 2, 2, 363, 364, 7, 112, 2, 2, 364, 365, 7, 119, 2, 2, 365, 366, 7, 110, 2, 2, 366, 367, 7, 110, 2, 2, 367, 66, 3, 2, 2, 2, 368, 369, 7, 113, 2, 2, 369, 370, 7, 116, 2, 2, 370, 68, 3, 2, 2, 2, 371, 372, 7, 43, 2, 2, 372, 70, 3, 2, 2, 2, 373, 374, 7, 118, 2, 2, 374, 375, 7, 116, 2, 2, 375, 376, 7, 119, 2, 2, 376, 383, 7, 103, 2, 2, 377, 378, 7, 104, 2, 2, 378, 379, 7, 99, 2, 2, 379, 380, 7, 110, 2, 2, 380, 381, 7, 117, 2, 2, 381, 383, 7, 103, 2, 2, 382, 373, 3, 2, 2, 2, 382, 377, 3, 2, 2, 2, 383, 72, 3, 2, 2, 2, 384, 385, 7, 63, 2, 2, 385, 395, 7, 63, 2, 2, 386, 387, 7, 35, 2, 2, 387, 395, 7, 63, 2, 2, 388, 395, 7, 62, 2, 2, 389, 390, 7, 62, 2, 2, 390, 395, 7, 63, 2, 2, 391, 395, 7, 64, 2, 2, 392, 393, 7, 64, 2, 2, 393, 395, 7, 63, 2, 2, 394, 384, 3, 2, 2, 2, 394, 386, 3, 2, 2, 2, 394, 388, 3, 2, 2, 2, 394, 389, 3, 2, 2, 2, 394, 391, 3, 2, 2, 2, 394, 392, 3, 2, 2, 2, 395, 74, 3, 2, 2, 2, 396, 397, 7, 45, 2, 2, 397, 76, 3, 2, 2, 2, 398, 399, 7, 47, 2, 2, 399, 78, 3, 2, 2, 2, 400, 401, 7, 44, 2, 2, 401, 80, 3, 2, 2, 2, 402, 403, 7, 49, 2, 2, 403, 82, 3, 2, 2, 2, 404, 405, 7, 39, 2, 2, 405, 84, 3, 2, 2, 2, 406, 407, 7, 99, 2, 2, 407, 408, 7, 117, 2, 2, 408, 414, 7, 101, 2, 2, 409, 410, 7, 102, 2, 2, 410, 411, 7, 103, 2, 2, 411, 412, 7, 117, 2, 2, 412, 414, 7, 101, 2, 2, 413, 406, 3, 2, 2, 2, 413, 409, 3, 2, 2, 2, 414, 86, 3, 2, 2, 2, 415, 416, 7, 112, 2, 2, 416, 417, 7, 119, 2, 2, 417, 418, 7, 110, 2, 2, 418, 419, 7, 110, 2, 2, 419, 420, 7, 117, 2, 2, 420, 88, 3, 2, 2, 2, 421, 422, 7, 104, 2, 2, 422, 423, 7, 107, 2, 2, 423, 424, 7, 116, 2, 2, 424, 425, 7, 117, 2, 2, 425, 431, 7, 118, 2, 2, 426, 427, 7, 110, 2, 2, 427, 428, 7, 99, 2, 2, 428, 429, 7, 117, 2, 2, 429, 431, 7, 118, 2, 2, 430, 421, 3, 2, 2, 2, 430, 426, 3, 2, 2, 2, 431, 90, 3, 2, 2, 2, 432, 433, 7, 116, 2, 2, 433, 434, 7, 113, 2, 2, 434, 435, 7, 119, 2, 2, 435, 436, 7, 112, 2, 2, 436, 450, 7, 102, 2, 2, 437, 438, 7, 99, 2, 2, 438, 439, 7, 120, 2, 2, 439, 450, 7, 105, 2, 2, 440, 441, 7, 111, 2, 2, 441, 442, 7, 107, 2, 2, 442, 450, 7, 112, 2, 2, 443, 444, 7, 111, 2, 2, 444, 445, 7, 99, 2, 2, 445, 450, 7, 122, 2, 2, 446, 447, 7, 117, 2, 2, 447, 448, 7, 119, 2, 2, 448, 450, 7, 111, 2, 2, 449, 432, 3, 2, 2, 2, 449, 437, 3, 2, 2, 2, 449, 440, 3, 2, 2, 2, 449, 443, 3, 2, 2, 2, 449, 446, 3, 2, 2, 2, 450, 92, 3, 2, 2, 2, 451, 454, 5, 33, 16, 2, 452, 454, 7, 97, 2, 2, 453, 451, 3, 2, 2, 2, 453, 452, 3, 2, 2, 2, 454, 460, 3, 2, 2, 2, 455, 459, 5, 33, 16, 2, 456, 459, 5, 31, 15, 2, 457, 459, 7, 97, 2, 2, 458, 455, 3, 2, 2, 2, 458, 456, 3, 2, 2, 2, 458, 457, 3, 2, 2, 2, 459, 462, 3, 2, 2, 2, 460, 458, 3, 2, 2, 2, 460, 461, 3, 2, 2, 2, 461, 94, 3, 2, 2, 2, 462, 460, 3, 2, 2, 2, 463, 469, 7, 98, 2, 2, 464, 468, 10, 10, 2, 2, 465, 466, 7, 98, 2, 2, 466, 468, 7, 98, 2, 2, 467, 464, 3, 2, 2, 2, 467, 465, 3, 2, 2, 2, 468, 471, 3, 2, 2, 2, 469, 467, 3, 2, 2, 2, 469, 470, 3, 2, 2, 2, 470, 472, 3, 2, 2, 2, 471, 469, 3, 2, 2, 2, 472, 473, 7, 98, 2, 2, 473, 96, 3, 2, 2, 2, 474, 475, 5, 23, 11, 2, 475, 476, 3, 2, 2, 2, 476, 477, 8, 48, 4, 2, 477, 98, 3, 2, 2, 2, 478, 479, 5, 25, 12, 2, 479, 480, 3, 2, 2, 2, 480, 481, 8, 49, 4, 2, 481, 100, 3, 2, 2, 2, 482, 483, 5, 27, 13, 2, 483, 484, 3, 2, 2, 2, 484, 485, 8, 50, 4, 2, 485, 102, 3, 2, 2, 2, 486, 487, 7, 126, 2, 2, 487, 488, 3, 2, 2, 2, 488, 489, 8, 51, 7, 2, 489, 490, 8, 51, 5, 2, 490, 104, 3, 2, 2, 2, 491, 492, 7, 95, 2, 2, 492, 493, 3, 2, 2, 2, 493, 494, 8, 52, 5, 2, 494, 495, 8, 52, 5, 2, 495, 496, 8, 52, 8, 2, 496, 106, 3, 2, 2, 2, 497, 498, 7, 46, 2, 2, 498, 499, 3, 2, 2, 2, 499, 500, 8, 53, 9, 2, 500, 108, 3, 2, 2, 2, 501, 502, 7, 63, 2, 2, 502, 503, 3, 2, 2, 2, 503, 504, 8, 54, 10, 2, 504, 110, 3, 2, 2, 2, 505, 507, 5, 113, 56, 2, 506, 505, 3, 2, 2, 2, 507, 508, 3, 2, 2, 2, 508, 506, 3, 2, 2, 2, 508, 509, 3, 2, 2, 2, 509, 112, 3, 2, 2, 2, 510, 512, 10, 11, 2, 2, 511, 510, 3, 2, 2, 2, 512, 513, 3, 2, 2, 2, 513, 511, 3, 2, 2, 2, 513, 514, 3, 2, 2, 2, 514, 518, 3, 2, 2, 2, 515, 516, 7, 49, 2, 2, 516, 518, 10, 12, 2, 2, 517, 511, 3, 2, 2, 2, 517, 515, 3, 2, 2, 2, 518, 114, 3, 2, 2, 2, 519, 520, 5, 95, 47, 2, 520, 116, 3, 2, 2, 2, 521, 522, 5, 23, 11, 2, 522, 523, 3, 2, 2, 2, 523, 524, 8, 58, 4, 2, 524, 118, 3, 2, 2, 2, 525, 526, 5, 25, 12, 2, 526, 527, 3, 2, 2, 2, 527, 528, 8, 59, 4, 2, 528, 120, 3, 2, 2, 2, 529, 530, 5, 27, 13, 2, 530, 531, 3, 2, 2, 2, 531, 532, 8, 60, 4, 2, 532, 122, 3, 2, 2, 2, 41, 2, 3, 4, 200, 204, 207, 216, 218, 229, 248, 253, 258, 260, 271, 279, 282, 284, 289, 294, 300, 307, 312, 318, 321, 329, 333, 382, 394, 413, 430, 449, 453, 458, 460, 467, 469, 508, 513, 517, 11, 7, 3, 2, 7, 4, 2, 2, 3, 2, 6, 2, 2, 7, 2, 2, 9, 15, 2, 9, 26, 2, 9, 22, 2, 9, 21, 2] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 83, 1396, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 4, 107, 9, 107, 4, 108, 9, 108, 4, 109, 9, 109, 4, 110, 9, 110, 4, 111, 9, 111, 4, 112, 9, 112, 4, 113, 9, 113, 4, 114, 9, 114, 4, 115, 9, 115, 4, 116, 9, 116, 4, 117, 9, 117, 4, 118, 9, 118, 4, 119, 9, 119, 4, 120, 9, 120, 4, 121, 9, 121, 4, 122, 9, 122, 4, 123, 9, 123, 4, 124, 9, 124, 4, 125, 9, 125, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 7, 19, 399, 10, 19, 12, 19, 14, 19, 402, 11, 19, 3, 19, 5, 19, 405, 10, 19, 3, 19, 5, 19, 408, 10, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 7, 20, 417, 10, 20, 12, 20, 14, 20, 420, 11, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 6, 21, 428, 10, 21, 13, 21, 14, 21, 429, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 5, 32, 471, 10, 32, 3, 32, 6, 32, 474, 10, 32, 13, 32, 14, 32, 475, 3, 33, 3, 33, 3, 33, 7, 33, 481, 10, 33, 12, 33, 14, 33, 484, 11, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 7, 33, 492, 10, 33, 12, 33, 14, 33, 495, 11, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 5, 33, 502, 10, 33, 3, 33, 5, 33, 505, 10, 33, 5, 33, 507, 10, 33, 3, 34, 6, 34, 510, 10, 34, 13, 34, 14, 34, 511, 3, 35, 6, 35, 515, 10, 35, 13, 35, 14, 35, 516, 3, 35, 3, 35, 7, 35, 521, 10, 35, 12, 35, 14, 35, 524, 11, 35, 3, 35, 3, 35, 6, 35, 528, 10, 35, 13, 35, 14, 35, 529, 3, 35, 6, 35, 533, 10, 35, 13, 35, 14, 35, 534, 3, 35, 3, 35, 7, 35, 539, 10, 35, 12, 35, 14, 35, 542, 11, 35, 5, 35, 544, 10, 35, 3, 35, 3, 35, 3, 35, 3, 35, 6, 35, 550, 10, 35, 13, 35, 14, 35, 551, 3, 35, 3, 35, 5, 35, 556, 10, 35, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 5, 37, 589, 10, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 5, 57, 673, 10, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 5, 58, 685, 10, 58, 3, 59, 3, 59, 3, 60, 3, 60, 3, 61, 3, 61, 3, 62, 3, 62, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 5, 65, 707, 10, 65, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 5, 67, 724, 10, 67, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 5, 68, 1088, 10, 68, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 5, 69, 1171, 10, 69, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 7, 71, 1189, 10, 71, 12, 71, 14, 71, 1192, 11, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 6, 71, 1199, 10, 71, 13, 71, 14, 71, 1200, 5, 71, 1203, 10, 71, 3, 72, 3, 72, 3, 72, 3, 72, 7, 72, 1209, 10, 72, 12, 72, 14, 72, 1212, 11, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 73, 3, 73, 3, 74, 3, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 75, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 79, 3, 79, 3, 79, 3, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 82, 6, 82, 1263, 10, 82, 13, 82, 14, 82, 1264, 3, 83, 6, 83, 1268, 10, 83, 13, 83, 14, 83, 1269, 3, 83, 3, 83, 5, 83, 1274, 10, 83, 3, 84, 3, 84, 3, 85, 3, 85, 3, 85, 3, 85, 3, 86, 3, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 3, 87, 3, 88, 3, 88, 3, 88, 3, 89, 3, 89, 3, 89, 3, 89, 3, 89, 3, 90, 3, 90, 3, 90, 3, 90, 3, 90, 3, 91, 3, 91, 3, 91, 3, 91, 3, 91, 3, 91, 3, 92, 3, 92, 3, 92, 3, 92, 3, 93, 3, 93, 3, 93, 3, 93, 3, 94, 6, 94, 1318, 10, 94, 13, 94, 14, 94, 1319, 3, 95, 6, 95, 1323, 10, 95, 13, 95, 14, 95, 1324, 3, 95, 3, 95, 5, 95, 1329, 10, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 97, 3, 97, 3, 98, 3, 98, 3, 98, 3, 98, 3, 99, 3, 99, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 102, 3, 102, 3, 103, 3, 103, 3, 104, 3, 104, 3, 105, 3, 105, 3, 106, 3, 106, 3, 107, 3, 107, 3, 108, 3, 108, 3, 109, 3, 109, 3, 110, 3, 110, 3, 111, 3, 111, 3, 112, 3, 112, 3, 113, 3, 113, 3, 114, 3, 114, 3, 115, 3, 115, 3, 116, 3, 116, 3, 117, 3, 117, 3, 118, 3, 118, 3, 119, 3, 119, 3, 120, 3, 120, 3, 121, 3, 121, 3, 122, 3, 122, 3, 123, 3, 123, 3, 124, 3, 124, 3, 125, 3, 125, 4, 418, 493, 2, 2, 126, 7, 2, 3, 9, 2, 4, 11, 2, 5, 13, 2, 6, 15, 2, 7, 17, 2, 8, 19, 2, 9, 21, 2, 10, 23, 2, 11, 25, 2, 12, 27, 2, 13, 29, 2, 14, 31, 2, 15, 33, 2, 16, 35, 2, 17, 37, 2, 18, 39, 2, 19, 41, 2, 20, 43, 2, 21, 45, 2, 22, 47, 2, 2, 49, 2, 83, 51, 2, 23, 53, 2, 24, 55, 2, 25, 57, 2, 26, 59, 2, 2, 61, 2, 2, 63, 2, 2, 65, 2, 2, 67, 2, 2, 69, 2, 27, 71, 2, 28, 73, 2, 29, 75, 2, 30, 77, 2, 31, 79, 2, 32, 81, 2, 33, 83, 2, 34, 85, 2, 35, 87, 2, 36, 89, 2, 37, 91, 2, 38, 93, 2, 39, 95, 2, 40, 97, 2, 41, 99, 2, 42, 101, 2, 43, 103, 2, 44, 105, 2, 45, 107, 2, 46, 109, 2, 47, 111, 2, 48, 113, 2, 49, 115, 2, 50, 117, 2, 51, 119, 2, 52, 121, 2, 53, 123, 2, 54, 125, 2, 55, 127, 2, 56, 129, 2, 57, 131, 2, 58, 133, 2, 59, 135, 2, 60, 137, 2, 61, 139, 2, 62, 141, 2, 63, 143, 2, 64, 145, 2, 65, 147, 2, 66, 149, 2, 67, 151, 2, 68, 153, 2, 69, 155, 2, 2, 157, 2, 2, 159, 2, 2, 161, 2, 2, 163, 2, 2, 165, 2, 70, 167, 2, 71, 169, 2, 2, 171, 2, 72, 173, 2, 73, 175, 2, 74, 177, 2, 75, 179, 2, 76, 181, 2, 77, 183, 2, 2, 185, 2, 2, 187, 2, 2, 189, 2, 2, 191, 2, 78, 193, 2, 2, 195, 2, 79, 197, 2, 80, 199, 2, 81, 201, 2, 82, 203, 2, 2, 205, 2, 2, 207, 2, 2, 209, 2, 2, 211, 2, 2, 213, 2, 2, 215, 2, 2, 217, 2, 2, 219, 2, 2, 221, 2, 2, 223, 2, 2, 225, 2, 2, 227, 2, 2, 229, 2, 2, 231, 2, 2, 233, 2, 2, 235, 2, 2, 237, 2, 2, 239, 2, 2, 241, 2, 2, 243, 2, 2, 245, 2, 2, 247, 2, 2, 249, 2, 2, 251, 2, 2, 253, 2, 2, 7, 2, 3, 4, 5, 6, 39, 4, 2, 12, 12, 15, 15, 5, 2, 11, 12, 15, 15, 34, 34, 3, 2, 50, 59, 4, 2, 67, 92, 99, 124, 7, 2, 36, 36, 94, 94, 112, 112, 116, 116, 118, 118, 6, 2, 12, 12, 15, 15, 36, 36, 94, 94, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 4, 2, 66, 66, 97, 97, 3, 2, 98, 98, 12, 2, 11, 12, 15, 15, 34, 34, 46, 46, 49, 49, 63, 63, 93, 93, 95, 95, 98, 98, 126, 126, 4, 2, 44, 44, 49, 49, 4, 2, 67, 67, 99, 99, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 2, 1464, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 3, 47, 3, 2, 2, 2, 3, 49, 3, 2, 2, 2, 3, 51, 3, 2, 2, 2, 3, 53, 3, 2, 2, 2, 3, 55, 3, 2, 2, 2, 4, 57, 3, 2, 2, 2, 4, 69, 3, 2, 2, 2, 4, 71, 3, 2, 2, 2, 4, 73, 3, 2, 2, 2, 4, 75, 3, 2, 2, 2, 4, 77, 3, 2, 2, 2, 4, 79, 3, 2, 2, 2, 4, 81, 3, 2, 2, 2, 4, 83, 3, 2, 2, 2, 4, 85, 3, 2, 2, 2, 4, 87, 3, 2, 2, 2, 4, 89, 3, 2, 2, 2, 4, 91, 3, 2, 2, 2, 4, 93, 3, 2, 2, 2, 4, 95, 3, 2, 2, 2, 4, 97, 3, 2, 2, 2, 4, 99, 3, 2, 2, 2, 4, 101, 3, 2, 2, 2, 4, 103, 3, 2, 2, 2, 4, 105, 3, 2, 2, 2, 4, 107, 3, 2, 2, 2, 4, 109, 3, 2, 2, 2, 4, 111, 3, 2, 2, 2, 4, 113, 3, 2, 2, 2, 4, 115, 3, 2, 2, 2, 4, 117, 3, 2, 2, 2, 4, 119, 3, 2, 2, 2, 4, 121, 3, 2, 2, 2, 4, 123, 3, 2, 2, 2, 4, 125, 3, 2, 2, 2, 4, 127, 3, 2, 2, 2, 4, 129, 3, 2, 2, 2, 4, 131, 3, 2, 2, 2, 4, 133, 3, 2, 2, 2, 4, 135, 3, 2, 2, 2, 4, 137, 3, 2, 2, 2, 4, 139, 3, 2, 2, 2, 4, 141, 3, 2, 2, 2, 4, 143, 3, 2, 2, 2, 4, 145, 3, 2, 2, 2, 4, 147, 3, 2, 2, 2, 4, 149, 3, 2, 2, 2, 4, 151, 3, 2, 2, 2, 4, 153, 3, 2, 2, 2, 5, 155, 3, 2, 2, 2, 5, 157, 3, 2, 2, 2, 5, 159, 3, 2, 2, 2, 5, 161, 3, 2, 2, 2, 5, 163, 3, 2, 2, 2, 5, 165, 3, 2, 2, 2, 5, 167, 3, 2, 2, 2, 5, 171, 3, 2, 2, 2, 5, 173, 3, 2, 2, 2, 5, 175, 3, 2, 2, 2, 5, 177, 3, 2, 2, 2, 6, 179, 3, 2, 2, 2, 6, 181, 3, 2, 2, 2, 6, 183, 3, 2, 2, 2, 6, 185, 3, 2, 2, 2, 6, 187, 3, 2, 2, 2, 6, 189, 3, 2, 2, 2, 6, 191, 3, 2, 2, 2, 6, 195, 3, 2, 2, 2, 6, 197, 3, 2, 2, 2, 6, 199, 3, 2, 2, 2, 6, 201, 3, 2, 2, 2, 7, 255, 3, 2, 2, 2, 9, 265, 3, 2, 2, 2, 11, 272, 3, 2, 2, 2, 13, 279, 3, 2, 2, 2, 15, 289, 3, 2, 2, 2, 17, 296, 3, 2, 2, 2, 19, 302, 3, 2, 2, 2, 21, 310, 3, 2, 2, 2, 23, 318, 3, 2, 2, 2, 25, 325, 3, 2, 2, 2, 27, 337, 3, 2, 2, 2, 29, 345, 3, 2, 2, 2, 31, 355, 3, 2, 2, 2, 33, 362, 3, 2, 2, 2, 35, 371, 3, 2, 2, 2, 37, 378, 3, 2, 2, 2, 39, 387, 3, 2, 2, 2, 41, 394, 3, 2, 2, 2, 43, 411, 3, 2, 2, 2, 45, 427, 3, 2, 2, 2, 47, 433, 3, 2, 2, 2, 49, 438, 3, 2, 2, 2, 51, 443, 3, 2, 2, 2, 53, 447, 3, 2, 2, 2, 55, 451, 3, 2, 2, 2, 57, 455, 3, 2, 2, 2, 59, 459, 3, 2, 2, 2, 61, 461, 3, 2, 2, 2, 63, 463, 3, 2, 2, 2, 65, 466, 3, 2, 2, 2, 67, 468, 3, 2, 2, 2, 69, 506, 3, 2, 2, 2, 71, 509, 3, 2, 2, 2, 73, 555, 3, 2, 2, 2, 75, 557, 3, 2, 2, 2, 77, 588, 3, 2, 2, 2, 79, 590, 3, 2, 2, 2, 81, 594, 3, 2, 2, 2, 83, 596, 3, 2, 2, 2, 85, 598, 3, 2, 2, 2, 87, 600, 3, 2, 2, 2, 89, 602, 3, 2, 2, 2, 91, 607, 3, 2, 2, 2, 93, 612, 3, 2, 2, 2, 95, 616, 3, 2, 2, 2, 97, 621, 3, 2, 2, 2, 99, 627, 3, 2, 2, 2, 101, 630, 3, 2, 2, 2, 103, 633, 3, 2, 2, 2, 105, 636, 3, 2, 2, 2, 107, 641, 3, 2, 2, 2, 109, 644, 3, 2, 2, 2, 111, 646, 3, 2, 2, 2, 113, 648, 3, 2, 2, 2, 115, 653, 3, 2, 2, 2, 117, 672, 3, 2, 2, 2, 119, 684, 3, 2, 2, 2, 121, 686, 3, 2, 2, 2, 123, 688, 3, 2, 2, 2, 125, 690, 3, 2, 2, 2, 127, 692, 3, 2, 2, 2, 129, 694, 3, 2, 2, 2, 131, 696, 3, 2, 2, 2, 133, 706, 3, 2, 2, 2, 135, 708, 3, 2, 2, 2, 137, 723, 3, 2, 2, 2, 139, 1087, 3, 2, 2, 2, 141, 1170, 3, 2, 2, 2, 143, 1172, 3, 2, 2, 2, 145, 1202, 3, 2, 2, 2, 147, 1204, 3, 2, 2, 2, 149, 1215, 3, 2, 2, 2, 151, 1219, 3, 2, 2, 2, 153, 1223, 3, 2, 2, 2, 155, 1227, 3, 2, 2, 2, 157, 1232, 3, 2, 2, 2, 159, 1238, 3, 2, 2, 2, 161, 1244, 3, 2, 2, 2, 163, 1248, 3, 2, 2, 2, 165, 1252, 3, 2, 2, 2, 167, 1262, 3, 2, 2, 2, 169, 1273, 3, 2, 2, 2, 171, 1275, 3, 2, 2, 2, 173, 1277, 3, 2, 2, 2, 175, 1281, 3, 2, 2, 2, 177, 1285, 3, 2, 2, 2, 179, 1289, 3, 2, 2, 2, 181, 1292, 3, 2, 2, 2, 183, 1297, 3, 2, 2, 2, 185, 1302, 3, 2, 2, 2, 187, 1308, 3, 2, 2, 2, 189, 1312, 3, 2, 2, 2, 191, 1317, 3, 2, 2, 2, 193, 1328, 3, 2, 2, 2, 195, 1330, 3, 2, 2, 2, 197, 1332, 3, 2, 2, 2, 199, 1336, 3, 2, 2, 2, 201, 1340, 3, 2, 2, 2, 203, 1344, 3, 2, 2, 2, 205, 1346, 3, 2, 2, 2, 207, 1348, 3, 2, 2, 2, 209, 1350, 3, 2, 2, 2, 211, 1352, 3, 2, 2, 2, 213, 1354, 3, 2, 2, 2, 215, 1356, 3, 2, 2, 2, 217, 1358, 3, 2, 2, 2, 219, 1360, 3, 2, 2, 2, 221, 1362, 3, 2, 2, 2, 223, 1364, 3, 2, 2, 2, 225, 1366, 3, 2, 2, 2, 227, 1368, 3, 2, 2, 2, 229, 1370, 3, 2, 2, 2, 231, 1372, 3, 2, 2, 2, 233, 1374, 3, 2, 2, 2, 235, 1376, 3, 2, 2, 2, 237, 1378, 3, 2, 2, 2, 239, 1380, 3, 2, 2, 2, 241, 1382, 3, 2, 2, 2, 243, 1384, 3, 2, 2, 2, 245, 1386, 3, 2, 2, 2, 247, 1388, 3, 2, 2, 2, 249, 1390, 3, 2, 2, 2, 251, 1392, 3, 2, 2, 2, 253, 1394, 3, 2, 2, 2, 255, 256, 5, 209, 103, 2, 256, 257, 5, 219, 108, 2, 257, 258, 5, 239, 118, 2, 258, 259, 5, 239, 118, 2, 259, 260, 5, 211, 104, 2, 260, 261, 5, 207, 102, 2, 261, 262, 5, 241, 119, 2, 262, 263, 3, 2, 2, 2, 263, 264, 8, 2, 2, 2, 264, 8, 3, 2, 2, 2, 265, 266, 5, 215, 106, 2, 266, 267, 5, 237, 117, 2, 267, 268, 5, 231, 114, 2, 268, 269, 5, 223, 110, 2, 269, 270, 3, 2, 2, 2, 270, 271, 8, 3, 2, 2, 271, 10, 3, 2, 2, 2, 272, 273, 5, 211, 104, 2, 273, 274, 5, 245, 121, 2, 274, 275, 5, 203, 100, 2, 275, 276, 5, 225, 111, 2, 276, 277, 3, 2, 2, 2, 277, 278, 8, 4, 2, 2, 278, 12, 3, 2, 2, 2, 279, 280, 5, 211, 104, 2, 280, 281, 5, 249, 123, 2, 281, 282, 5, 233, 115, 2, 282, 283, 5, 225, 111, 2, 283, 284, 5, 203, 100, 2, 284, 285, 5, 219, 108, 2, 285, 286, 5, 229, 113, 2, 286, 287, 3, 2, 2, 2, 287, 288, 8, 5, 3, 2, 288, 14, 3, 2, 2, 2, 289, 290, 5, 213, 105, 2, 290, 291, 5, 237, 117, 2, 291, 292, 5, 231, 114, 2, 292, 293, 5, 227, 112, 2, 293, 294, 3, 2, 2, 2, 294, 295, 8, 6, 4, 2, 295, 16, 3, 2, 2, 2, 296, 297, 5, 237, 117, 2, 297, 298, 5, 231, 114, 2, 298, 299, 5, 247, 122, 2, 299, 300, 3, 2, 2, 2, 300, 301, 8, 7, 2, 2, 301, 18, 3, 2, 2, 2, 302, 303, 5, 239, 118, 2, 303, 304, 5, 241, 119, 2, 304, 305, 5, 203, 100, 2, 305, 306, 5, 241, 119, 2, 306, 307, 5, 239, 118, 2, 307, 308, 3, 2, 2, 2, 308, 309, 8, 8, 2, 2, 309, 20, 3, 2, 2, 2, 310, 311, 5, 247, 122, 2, 311, 312, 5, 217, 107, 2, 312, 313, 5, 211, 104, 2, 313, 314, 5, 237, 117, 2, 314, 315, 5, 211, 104, 2, 315, 316, 3, 2, 2, 2, 316, 317, 8, 9, 2, 2, 317, 22, 3, 2, 2, 2, 318, 319, 5, 239, 118, 2, 319, 320, 5, 231, 114, 2, 320, 321, 5, 237, 117, 2, 321, 322, 5, 241, 119, 2, 322, 323, 3, 2, 2, 2, 323, 324, 8, 10, 2, 2, 324, 24, 3, 2, 2, 2, 325, 326, 5, 227, 112, 2, 326, 327, 5, 245, 121, 2, 327, 328, 5, 111, 54, 2, 328, 329, 5, 211, 104, 2, 329, 330, 5, 249, 123, 2, 330, 331, 5, 233, 115, 2, 331, 332, 5, 203, 100, 2, 332, 333, 5, 229, 113, 2, 333, 334, 5, 209, 103, 2, 334, 335, 3, 2, 2, 2, 335, 336, 8, 11, 2, 2, 336, 26, 3, 2, 2, 2, 337, 338, 5, 225, 111, 2, 338, 339, 5, 219, 108, 2, 339, 340, 5, 227, 112, 2, 340, 341, 5, 219, 108, 2, 341, 342, 5, 241, 119, 2, 342, 343, 3, 2, 2, 2, 343, 344, 8, 12, 2, 2, 344, 28, 3, 2, 2, 2, 345, 346, 5, 233, 115, 2, 346, 347, 5, 237, 117, 2, 347, 348, 5, 231, 114, 2, 348, 349, 5, 221, 109, 2, 349, 350, 5, 211, 104, 2, 350, 351, 5, 207, 102, 2, 351, 352, 5, 241, 119, 2, 352, 353, 3, 2, 2, 2, 353, 354, 8, 13, 2, 2, 354, 30, 3, 2, 2, 2, 355, 356, 5, 209, 103, 2, 356, 357, 5, 237, 117, 2, 357, 358, 5, 231, 114, 2, 358, 359, 5, 233, 115, 2, 359, 360, 3, 2, 2, 2, 360, 361, 8, 14, 2, 2, 361, 32, 3, 2, 2, 2, 362, 363, 5, 237, 117, 2, 363, 364, 5, 211, 104, 2, 364, 365, 5, 229, 113, 2, 365, 366, 5, 203, 100, 2, 366, 367, 5, 227, 112, 2, 367, 368, 5, 211, 104, 2, 368, 369, 3, 2, 2, 2, 369, 370, 8, 15, 2, 2, 370, 34, 3, 2, 2, 2, 371, 372, 5, 239, 118, 2, 372, 373, 5, 217, 107, 2, 373, 374, 5, 231, 114, 2, 374, 375, 5, 247, 122, 2, 375, 376, 3, 2, 2, 2, 376, 377, 8, 16, 2, 2, 377, 36, 3, 2, 2, 2, 378, 379, 5, 211, 104, 2, 379, 380, 5, 229, 113, 2, 380, 381, 5, 237, 117, 2, 381, 382, 5, 219, 108, 2, 382, 383, 5, 207, 102, 2, 383, 384, 5, 217, 107, 2, 384, 385, 3, 2, 2, 2, 385, 386, 8, 17, 5, 2, 386, 38, 3, 2, 2, 2, 387, 388, 5, 223, 110, 2, 388, 389, 5, 211, 104, 2, 389, 390, 5, 211, 104, 2, 390, 391, 5, 233, 115, 2, 391, 392, 3, 2, 2, 2, 392, 393, 8, 18, 2, 2, 393, 40, 3, 2, 2, 2, 394, 395, 7, 49, 2, 2, 395, 396, 7, 49, 2, 2, 396, 400, 3, 2, 2, 2, 397, 399, 10, 2, 2, 2, 398, 397, 3, 2, 2, 2, 399, 402, 3, 2, 2, 2, 400, 398, 3, 2, 2, 2, 400, 401, 3, 2, 2, 2, 401, 404, 3, 2, 2, 2, 402, 400, 3, 2, 2, 2, 403, 405, 7, 15, 2, 2, 404, 403, 3, 2, 2, 2, 404, 405, 3, 2, 2, 2, 405, 407, 3, 2, 2, 2, 406, 408, 7, 12, 2, 2, 407, 406, 3, 2, 2, 2, 407, 408, 3, 2, 2, 2, 408, 409, 3, 2, 2, 2, 409, 410, 8, 19, 6, 2, 410, 42, 3, 2, 2, 2, 411, 412, 7, 49, 2, 2, 412, 413, 7, 44, 2, 2, 413, 418, 3, 2, 2, 2, 414, 417, 5, 43, 20, 2, 415, 417, 11, 2, 2, 2, 416, 414, 3, 2, 2, 2, 416, 415, 3, 2, 2, 2, 417, 420, 3, 2, 2, 2, 418, 419, 3, 2, 2, 2, 418, 416, 3, 2, 2, 2, 419, 421, 3, 2, 2, 2, 420, 418, 3, 2, 2, 2, 421, 422, 7, 44, 2, 2, 422, 423, 7, 49, 2, 2, 423, 424, 3, 2, 2, 2, 424, 425, 8, 20, 6, 2, 425, 44, 3, 2, 2, 2, 426, 428, 9, 3, 2, 2, 427, 426, 3, 2, 2, 2, 428, 429, 3, 2, 2, 2, 429, 427, 3, 2, 2, 2, 429, 430, 3, 2, 2, 2, 430, 431, 3, 2, 2, 2, 431, 432, 8, 21, 6, 2, 432, 46, 3, 2, 2, 2, 433, 434, 7, 93, 2, 2, 434, 435, 3, 2, 2, 2, 435, 436, 8, 22, 7, 2, 436, 437, 8, 22, 8, 2, 437, 48, 3, 2, 2, 2, 438, 439, 7, 126, 2, 2, 439, 440, 3, 2, 2, 2, 440, 441, 8, 23, 9, 2, 441, 442, 8, 23, 10, 2, 442, 50, 3, 2, 2, 2, 443, 444, 5, 45, 21, 2, 444, 445, 3, 2, 2, 2, 445, 446, 8, 24, 6, 2, 446, 52, 3, 2, 2, 2, 447, 448, 5, 41, 19, 2, 448, 449, 3, 2, 2, 2, 449, 450, 8, 25, 6, 2, 450, 54, 3, 2, 2, 2, 451, 452, 5, 43, 20, 2, 452, 453, 3, 2, 2, 2, 453, 454, 8, 26, 6, 2, 454, 56, 3, 2, 2, 2, 455, 456, 7, 126, 2, 2, 456, 457, 3, 2, 2, 2, 457, 458, 8, 27, 10, 2, 458, 58, 3, 2, 2, 2, 459, 460, 9, 4, 2, 2, 460, 60, 3, 2, 2, 2, 461, 462, 9, 5, 2, 2, 462, 62, 3, 2, 2, 2, 463, 464, 7, 94, 2, 2, 464, 465, 9, 6, 2, 2, 465, 64, 3, 2, 2, 2, 466, 467, 10, 7, 2, 2, 467, 66, 3, 2, 2, 2, 468, 470, 9, 8, 2, 2, 469, 471, 9, 9, 2, 2, 470, 469, 3, 2, 2, 2, 470, 471, 3, 2, 2, 2, 471, 473, 3, 2, 2, 2, 472, 474, 5, 59, 28, 2, 473, 472, 3, 2, 2, 2, 474, 475, 3, 2, 2, 2, 475, 473, 3, 2, 2, 2, 475, 476, 3, 2, 2, 2, 476, 68, 3, 2, 2, 2, 477, 482, 7, 36, 2, 2, 478, 481, 5, 63, 30, 2, 479, 481, 5, 65, 31, 2, 480, 478, 3, 2, 2, 2, 480, 479, 3, 2, 2, 2, 481, 484, 3, 2, 2, 2, 482, 480, 3, 2, 2, 2, 482, 483, 3, 2, 2, 2, 483, 485, 3, 2, 2, 2, 484, 482, 3, 2, 2, 2, 485, 507, 7, 36, 2, 2, 486, 487, 7, 36, 2, 2, 487, 488, 7, 36, 2, 2, 488, 489, 7, 36, 2, 2, 489, 493, 3, 2, 2, 2, 490, 492, 10, 2, 2, 2, 491, 490, 3, 2, 2, 2, 492, 495, 3, 2, 2, 2, 493, 494, 3, 2, 2, 2, 493, 491, 3, 2, 2, 2, 494, 496, 3, 2, 2, 2, 495, 493, 3, 2, 2, 2, 496, 497, 7, 36, 2, 2, 497, 498, 7, 36, 2, 2, 498, 499, 7, 36, 2, 2, 499, 501, 3, 2, 2, 2, 500, 502, 7, 36, 2, 2, 501, 500, 3, 2, 2, 2, 501, 502, 3, 2, 2, 2, 502, 504, 3, 2, 2, 2, 503, 505, 7, 36, 2, 2, 504, 503, 3, 2, 2, 2, 504, 505, 3, 2, 2, 2, 505, 507, 3, 2, 2, 2, 506, 477, 3, 2, 2, 2, 506, 486, 3, 2, 2, 2, 507, 70, 3, 2, 2, 2, 508, 510, 5, 59, 28, 2, 509, 508, 3, 2, 2, 2, 510, 511, 3, 2, 2, 2, 511, 509, 3, 2, 2, 2, 511, 512, 3, 2, 2, 2, 512, 72, 3, 2, 2, 2, 513, 515, 5, 59, 28, 2, 514, 513, 3, 2, 2, 2, 515, 516, 3, 2, 2, 2, 516, 514, 3, 2, 2, 2, 516, 517, 3, 2, 2, 2, 517, 518, 3, 2, 2, 2, 518, 522, 5, 85, 41, 2, 519, 521, 5, 59, 28, 2, 520, 519, 3, 2, 2, 2, 521, 524, 3, 2, 2, 2, 522, 520, 3, 2, 2, 2, 522, 523, 3, 2, 2, 2, 523, 556, 3, 2, 2, 2, 524, 522, 3, 2, 2, 2, 525, 527, 5, 85, 41, 2, 526, 528, 5, 59, 28, 2, 527, 526, 3, 2, 2, 2, 528, 529, 3, 2, 2, 2, 529, 527, 3, 2, 2, 2, 529, 530, 3, 2, 2, 2, 530, 556, 3, 2, 2, 2, 531, 533, 5, 59, 28, 2, 532, 531, 3, 2, 2, 2, 533, 534, 3, 2, 2, 2, 534, 532, 3, 2, 2, 2, 534, 535, 3, 2, 2, 2, 535, 543, 3, 2, 2, 2, 536, 540, 5, 85, 41, 2, 537, 539, 5, 59, 28, 2, 538, 537, 3, 2, 2, 2, 539, 542, 3, 2, 2, 2, 540, 538, 3, 2, 2, 2, 540, 541, 3, 2, 2, 2, 541, 544, 3, 2, 2, 2, 542, 540, 3, 2, 2, 2, 543, 536, 3, 2, 2, 2, 543, 544, 3, 2, 2, 2, 544, 545, 3, 2, 2, 2, 545, 546, 5, 67, 32, 2, 546, 556, 3, 2, 2, 2, 547, 549, 5, 85, 41, 2, 548, 550, 5, 59, 28, 2, 549, 548, 3, 2, 2, 2, 550, 551, 3, 2, 2, 2, 551, 549, 3, 2, 2, 2, 551, 552, 3, 2, 2, 2, 552, 553, 3, 2, 2, 2, 553, 554, 5, 67, 32, 2, 554, 556, 3, 2, 2, 2, 555, 514, 3, 2, 2, 2, 555, 525, 3, 2, 2, 2, 555, 532, 3, 2, 2, 2, 555, 547, 3, 2, 2, 2, 556, 74, 3, 2, 2, 2, 557, 558, 7, 100, 2, 2, 558, 559, 7, 123, 2, 2, 559, 76, 3, 2, 2, 2, 560, 561, 7, 123, 2, 2, 561, 562, 7, 103, 2, 2, 562, 563, 7, 99, 2, 2, 563, 589, 7, 116, 2, 2, 564, 565, 7, 111, 2, 2, 565, 566, 7, 113, 2, 2, 566, 567, 7, 112, 2, 2, 567, 568, 7, 118, 2, 2, 568, 589, 7, 106, 2, 2, 569, 570, 7, 102, 2, 2, 570, 571, 7, 99, 2, 2, 571, 589, 7, 123, 2, 2, 572, 573, 7, 117, 2, 2, 573, 574, 7, 103, 2, 2, 574, 575, 7, 101, 2, 2, 575, 576, 7, 113, 2, 2, 576, 577, 7, 112, 2, 2, 577, 589, 7, 102, 2, 2, 578, 579, 7, 111, 2, 2, 579, 580, 7, 107, 2, 2, 580, 581, 7, 112, 2, 2, 581, 582, 7, 119, 2, 2, 582, 583, 7, 118, 2, 2, 583, 589, 7, 103, 2, 2, 584, 585, 7, 106, 2, 2, 585, 586, 7, 113, 2, 2, 586, 587, 7, 119, 2, 2, 587, 589, 7, 116, 2, 2, 588, 560, 3, 2, 2, 2, 588, 564, 3, 2, 2, 2, 588, 569, 3, 2, 2, 2, 588, 572, 3, 2, 2, 2, 588, 578, 3, 2, 2, 2, 588, 584, 3, 2, 2, 2, 589, 78, 3, 2, 2, 2, 590, 591, 7, 99, 2, 2, 591, 592, 7, 112, 2, 2, 592, 593, 7, 102, 2, 2, 593, 80, 3, 2, 2, 2, 594, 595, 7, 63, 2, 2, 595, 82, 3, 2, 2, 2, 596, 597, 7, 46, 2, 2, 597, 84, 3, 2, 2, 2, 598, 599, 7, 48, 2, 2, 599, 86, 3, 2, 2, 2, 600, 601, 7, 42, 2, 2, 601, 88, 3, 2, 2, 2, 602, 603, 7, 93, 2, 2, 603, 604, 3, 2, 2, 2, 604, 605, 8, 43, 2, 2, 605, 606, 8, 43, 2, 2, 606, 90, 3, 2, 2, 2, 607, 608, 7, 95, 2, 2, 608, 609, 3, 2, 2, 2, 609, 610, 8, 44, 10, 2, 610, 611, 8, 44, 10, 2, 611, 92, 3, 2, 2, 2, 612, 613, 5, 229, 113, 2, 613, 614, 5, 231, 114, 2, 614, 615, 5, 241, 119, 2, 615, 94, 3, 2, 2, 2, 616, 617, 5, 225, 111, 2, 617, 618, 5, 219, 108, 2, 618, 619, 5, 223, 110, 2, 619, 620, 5, 211, 104, 2, 620, 96, 3, 2, 2, 2, 621, 622, 5, 237, 117, 2, 622, 623, 5, 225, 111, 2, 623, 624, 5, 219, 108, 2, 624, 625, 5, 223, 110, 2, 625, 626, 5, 211, 104, 2, 626, 98, 3, 2, 2, 2, 627, 628, 5, 219, 108, 2, 628, 629, 5, 229, 113, 2, 629, 100, 3, 2, 2, 2, 630, 631, 5, 219, 108, 2, 631, 632, 5, 239, 118, 2, 632, 102, 3, 2, 2, 2, 633, 634, 5, 203, 100, 2, 634, 635, 5, 239, 118, 2, 635, 104, 3, 2, 2, 2, 636, 637, 5, 229, 113, 2, 637, 638, 5, 243, 120, 2, 638, 639, 5, 225, 111, 2, 639, 640, 5, 225, 111, 2, 640, 106, 3, 2, 2, 2, 641, 642, 7, 113, 2, 2, 642, 643, 7, 116, 2, 2, 643, 108, 3, 2, 2, 2, 644, 645, 7, 43, 2, 2, 645, 110, 3, 2, 2, 2, 646, 647, 7, 97, 2, 2, 647, 112, 3, 2, 2, 2, 648, 649, 7, 107, 2, 2, 649, 650, 7, 112, 2, 2, 650, 651, 7, 104, 2, 2, 651, 652, 7, 113, 2, 2, 652, 114, 3, 2, 2, 2, 653, 654, 7, 104, 2, 2, 654, 655, 7, 119, 2, 2, 655, 656, 7, 112, 2, 2, 656, 657, 7, 101, 2, 2, 657, 658, 7, 118, 2, 2, 658, 659, 7, 107, 2, 2, 659, 660, 7, 113, 2, 2, 660, 661, 7, 112, 2, 2, 661, 662, 7, 117, 2, 2, 662, 116, 3, 2, 2, 2, 663, 664, 7, 118, 2, 2, 664, 665, 7, 116, 2, 2, 665, 666, 7, 119, 2, 2, 666, 673, 7, 103, 2, 2, 667, 668, 7, 104, 2, 2, 668, 669, 7, 99, 2, 2, 669, 670, 7, 110, 2, 2, 670, 671, 7, 117, 2, 2, 671, 673, 7, 103, 2, 2, 672, 663, 3, 2, 2, 2, 672, 667, 3, 2, 2, 2, 673, 118, 3, 2, 2, 2, 674, 675, 7, 63, 2, 2, 675, 685, 7, 63, 2, 2, 676, 677, 7, 35, 2, 2, 677, 685, 7, 63, 2, 2, 678, 685, 7, 62, 2, 2, 679, 680, 7, 62, 2, 2, 680, 685, 7, 63, 2, 2, 681, 685, 7, 64, 2, 2, 682, 683, 7, 64, 2, 2, 683, 685, 7, 63, 2, 2, 684, 674, 3, 2, 2, 2, 684, 676, 3, 2, 2, 2, 684, 678, 3, 2, 2, 2, 684, 679, 3, 2, 2, 2, 684, 681, 3, 2, 2, 2, 684, 682, 3, 2, 2, 2, 685, 120, 3, 2, 2, 2, 686, 687, 7, 45, 2, 2, 687, 122, 3, 2, 2, 2, 688, 689, 7, 47, 2, 2, 689, 124, 3, 2, 2, 2, 690, 691, 7, 44, 2, 2, 691, 126, 3, 2, 2, 2, 692, 693, 7, 49, 2, 2, 693, 128, 3, 2, 2, 2, 694, 695, 7, 39, 2, 2, 695, 130, 3, 2, 2, 2, 696, 697, 7, 51, 2, 2, 697, 698, 7, 50, 2, 2, 698, 132, 3, 2, 2, 2, 699, 700, 7, 99, 2, 2, 700, 701, 7, 117, 2, 2, 701, 707, 7, 101, 2, 2, 702, 703, 7, 102, 2, 2, 703, 704, 7, 103, 2, 2, 704, 705, 7, 117, 2, 2, 705, 707, 7, 101, 2, 2, 706, 699, 3, 2, 2, 2, 706, 702, 3, 2, 2, 2, 707, 134, 3, 2, 2, 2, 708, 709, 7, 112, 2, 2, 709, 710, 7, 119, 2, 2, 710, 711, 7, 110, 2, 2, 711, 712, 7, 110, 2, 2, 712, 713, 7, 117, 2, 2, 713, 136, 3, 2, 2, 2, 714, 715, 7, 104, 2, 2, 715, 716, 7, 107, 2, 2, 716, 717, 7, 116, 2, 2, 717, 718, 7, 117, 2, 2, 718, 724, 7, 118, 2, 2, 719, 720, 7, 110, 2, 2, 720, 721, 7, 99, 2, 2, 721, 722, 7, 117, 2, 2, 722, 724, 7, 118, 2, 2, 723, 714, 3, 2, 2, 2, 723, 719, 3, 2, 2, 2, 724, 138, 3, 2, 2, 2, 725, 726, 5, 237, 117, 2, 726, 727, 5, 231, 114, 2, 727, 728, 5, 243, 120, 2, 728, 729, 5, 229, 113, 2, 729, 730, 5, 209, 103, 2, 730, 1088, 3, 2, 2, 2, 731, 732, 5, 203, 100, 2, 732, 733, 5, 205, 101, 2, 733, 734, 5, 239, 118, 2, 734, 1088, 3, 2, 2, 2, 735, 736, 5, 233, 115, 2, 736, 737, 5, 231, 114, 2, 737, 738, 5, 247, 122, 2, 738, 1088, 3, 2, 2, 2, 739, 740, 5, 225, 111, 2, 740, 741, 5, 231, 114, 2, 741, 742, 5, 215, 106, 2, 742, 743, 5, 131, 64, 2, 743, 1088, 3, 2, 2, 2, 744, 745, 5, 233, 115, 2, 745, 746, 5, 219, 108, 2, 746, 1088, 3, 2, 2, 2, 747, 748, 5, 241, 119, 2, 748, 749, 5, 203, 100, 2, 749, 750, 5, 243, 120, 2, 750, 1088, 3, 2, 2, 2, 751, 1088, 5, 211, 104, 2, 752, 753, 5, 239, 118, 2, 753, 754, 5, 243, 120, 2, 754, 755, 5, 205, 101, 2, 755, 756, 5, 239, 118, 2, 756, 757, 5, 241, 119, 2, 757, 758, 5, 237, 117, 2, 758, 759, 5, 219, 108, 2, 759, 760, 5, 229, 113, 2, 760, 761, 5, 215, 106, 2, 761, 1088, 3, 2, 2, 2, 762, 763, 5, 241, 119, 2, 763, 764, 5, 237, 117, 2, 764, 765, 5, 219, 108, 2, 765, 766, 5, 227, 112, 2, 766, 1088, 3, 2, 2, 2, 767, 768, 5, 207, 102, 2, 768, 769, 5, 231, 114, 2, 769, 770, 5, 229, 113, 2, 770, 771, 5, 207, 102, 2, 771, 772, 5, 203, 100, 2, 772, 773, 5, 241, 119, 2, 773, 1088, 3, 2, 2, 2, 774, 775, 5, 239, 118, 2, 775, 776, 5, 241, 119, 2, 776, 777, 5, 203, 100, 2, 777, 778, 5, 237, 117, 2, 778, 779, 5, 241, 119, 2, 779, 780, 5, 239, 118, 2, 780, 781, 5, 111, 54, 2, 781, 782, 5, 247, 122, 2, 782, 783, 5, 219, 108, 2, 783, 784, 5, 241, 119, 2, 784, 785, 5, 217, 107, 2, 785, 1088, 3, 2, 2, 2, 786, 787, 5, 209, 103, 2, 787, 788, 5, 203, 100, 2, 788, 789, 5, 241, 119, 2, 789, 790, 5, 211, 104, 2, 790, 791, 5, 111, 54, 2, 791, 792, 5, 213, 105, 2, 792, 793, 5, 231, 114, 2, 793, 794, 5, 237, 117, 2, 794, 795, 5, 227, 112, 2, 795, 796, 5, 203, 100, 2, 796, 797, 5, 241, 119, 2, 797, 1088, 3, 2, 2, 2, 798, 799, 5, 209, 103, 2, 799, 800, 5, 203, 100, 2, 800, 801, 5, 241, 119, 2, 801, 802, 5, 211, 104, 2, 802, 803, 5, 111, 54, 2, 803, 804, 5, 241, 119, 2, 804, 805, 5, 237, 117, 2, 805, 806, 5, 243, 120, 2, 806, 807, 5, 229, 113, 2, 807, 808, 5, 207, 102, 2, 808, 1088, 3, 2, 2, 2, 809, 810, 5, 209, 103, 2, 810, 811, 5, 203, 100, 2, 811, 812, 5, 241, 119, 2, 812, 813, 5, 211, 104, 2, 813, 814, 5, 111, 54, 2, 814, 815, 5, 233, 115, 2, 815, 816, 5, 203, 100, 2, 816, 817, 5, 237, 117, 2, 817, 818, 5, 239, 118, 2, 818, 819, 5, 211, 104, 2, 819, 1088, 3, 2, 2, 2, 820, 821, 5, 203, 100, 2, 821, 822, 5, 243, 120, 2, 822, 823, 5, 241, 119, 2, 823, 824, 5, 231, 114, 2, 824, 825, 5, 111, 54, 2, 825, 826, 5, 205, 101, 2, 826, 827, 5, 243, 120, 2, 827, 828, 5, 207, 102, 2, 828, 829, 5, 223, 110, 2, 829, 830, 5, 211, 104, 2, 830, 831, 5, 241, 119, 2, 831, 1088, 3, 2, 2, 2, 832, 833, 5, 219, 108, 2, 833, 834, 5, 239, 118, 2, 834, 835, 5, 111, 54, 2, 835, 836, 5, 213, 105, 2, 836, 837, 5, 219, 108, 2, 837, 838, 5, 229, 113, 2, 838, 839, 5, 219, 108, 2, 839, 840, 5, 241, 119, 2, 840, 841, 5, 211, 104, 2, 841, 1088, 3, 2, 2, 2, 842, 843, 5, 219, 108, 2, 843, 844, 5, 239, 118, 2, 844, 845, 5, 111, 54, 2, 845, 846, 5, 219, 108, 2, 846, 847, 5, 229, 113, 2, 847, 848, 5, 213, 105, 2, 848, 849, 5, 219, 108, 2, 849, 850, 5, 229, 113, 2, 850, 851, 5, 219, 108, 2, 851, 852, 5, 241, 119, 2, 852, 853, 5, 211, 104, 2, 853, 1088, 3, 2, 2, 2, 854, 855, 5, 207, 102, 2, 855, 856, 5, 203, 100, 2, 856, 857, 5, 239, 118, 2, 857, 858, 5, 211, 104, 2, 858, 1088, 3, 2, 2, 2, 859, 860, 5, 225, 111, 2, 860, 861, 5, 211, 104, 2, 861, 862, 5, 229, 113, 2, 862, 863, 5, 215, 106, 2, 863, 864, 5, 241, 119, 2, 864, 865, 5, 217, 107, 2, 865, 1088, 3, 2, 2, 2, 866, 867, 5, 227, 112, 2, 867, 868, 5, 245, 121, 2, 868, 869, 5, 111, 54, 2, 869, 870, 5, 227, 112, 2, 870, 871, 5, 203, 100, 2, 871, 872, 5, 249, 123, 2, 872, 1088, 3, 2, 2, 2, 873, 874, 5, 227, 112, 2, 874, 875, 5, 245, 121, 2, 875, 876, 5, 111, 54, 2, 876, 877, 5, 227, 112, 2, 877, 878, 5, 219, 108, 2, 878, 879, 5, 229, 113, 2, 879, 1088, 3, 2, 2, 2, 880, 881, 5, 227, 112, 2, 881, 882, 5, 245, 121, 2, 882, 883, 5, 111, 54, 2, 883, 884, 5, 203, 100, 2, 884, 885, 5, 245, 121, 2, 885, 886, 5, 215, 106, 2, 886, 1088, 3, 2, 2, 2, 887, 888, 5, 227, 112, 2, 888, 889, 5, 245, 121, 2, 889, 890, 5, 111, 54, 2, 890, 891, 5, 239, 118, 2, 891, 892, 5, 243, 120, 2, 892, 893, 5, 227, 112, 2, 893, 1088, 3, 2, 2, 2, 894, 895, 5, 227, 112, 2, 895, 896, 5, 245, 121, 2, 896, 897, 5, 111, 54, 2, 897, 898, 5, 207, 102, 2, 898, 899, 5, 231, 114, 2, 899, 900, 5, 243, 120, 2, 900, 901, 5, 229, 113, 2, 901, 902, 5, 241, 119, 2, 902, 1088, 3, 2, 2, 2, 903, 904, 5, 227, 112, 2, 904, 905, 5, 245, 121, 2, 905, 906, 5, 111, 54, 2, 906, 907, 5, 207, 102, 2, 907, 908, 5, 231, 114, 2, 908, 909, 5, 229, 113, 2, 909, 910, 5, 207, 102, 2, 910, 911, 5, 203, 100, 2, 911, 912, 5, 241, 119, 2, 912, 1088, 3, 2, 2, 2, 913, 914, 5, 227, 112, 2, 914, 915, 5, 245, 121, 2, 915, 916, 5, 111, 54, 2, 916, 917, 5, 221, 109, 2, 917, 918, 5, 231, 114, 2, 918, 919, 5, 219, 108, 2, 919, 920, 5, 229, 113, 2, 920, 1088, 3, 2, 2, 2, 921, 922, 5, 227, 112, 2, 922, 923, 5, 245, 121, 2, 923, 924, 5, 111, 54, 2, 924, 925, 5, 227, 112, 2, 925, 926, 5, 211, 104, 2, 926, 927, 5, 209, 103, 2, 927, 928, 5, 219, 108, 2, 928, 929, 5, 203, 100, 2, 929, 930, 5, 229, 113, 2, 930, 1088, 3, 2, 2, 2, 931, 932, 5, 227, 112, 2, 932, 933, 5, 245, 121, 2, 933, 934, 5, 111, 54, 2, 934, 935, 5, 209, 103, 2, 935, 936, 5, 211, 104, 2, 936, 937, 5, 209, 103, 2, 937, 938, 5, 243, 120, 2, 938, 939, 5, 233, 115, 2, 939, 940, 5, 211, 104, 2, 940, 1088, 3, 2, 2, 2, 941, 942, 5, 227, 112, 2, 942, 943, 5, 211, 104, 2, 943, 944, 5, 241, 119, 2, 944, 945, 5, 203, 100, 2, 945, 946, 5, 209, 103, 2, 946, 947, 5, 203, 100, 2, 947, 948, 5, 241, 119, 2, 948, 949, 5, 203, 100, 2, 949, 1088, 3, 2, 2, 2, 950, 951, 5, 239, 118, 2, 951, 952, 5, 233, 115, 2, 952, 953, 5, 225, 111, 2, 953, 954, 5, 219, 108, 2, 954, 955, 5, 241, 119, 2, 955, 1088, 3, 2, 2, 2, 956, 957, 5, 241, 119, 2, 957, 958, 5, 231, 114, 2, 958, 959, 5, 111, 54, 2, 959, 960, 5, 239, 118, 2, 960, 961, 5, 241, 119, 2, 961, 962, 5, 237, 117, 2, 962, 963, 5, 219, 108, 2, 963, 964, 5, 229, 113, 2, 964, 965, 5, 215, 106, 2, 965, 1088, 3, 2, 2, 2, 966, 967, 5, 241, 119, 2, 967, 968, 5, 231, 114, 2, 968, 969, 5, 111, 54, 2, 969, 970, 5, 239, 118, 2, 970, 971, 5, 241, 119, 2, 971, 972, 5, 237, 117, 2, 972, 1088, 3, 2, 2, 2, 973, 974, 5, 241, 119, 2, 974, 975, 5, 231, 114, 2, 975, 976, 5, 111, 54, 2, 976, 977, 5, 205, 101, 2, 977, 978, 5, 231, 114, 2, 978, 979, 5, 231, 114, 2, 979, 980, 5, 225, 111, 2, 980, 1088, 3, 2, 2, 2, 981, 982, 5, 241, 119, 2, 982, 983, 5, 231, 114, 2, 983, 984, 5, 111, 54, 2, 984, 985, 5, 205, 101, 2, 985, 986, 5, 231, 114, 2, 986, 987, 5, 231, 114, 2, 987, 988, 5, 225, 111, 2, 988, 989, 5, 211, 104, 2, 989, 990, 5, 203, 100, 2, 990, 991, 5, 229, 113, 2, 991, 1088, 3, 2, 2, 2, 992, 993, 5, 241, 119, 2, 993, 994, 5, 231, 114, 2, 994, 995, 5, 111, 54, 2, 995, 996, 5, 209, 103, 2, 996, 997, 5, 203, 100, 2, 997, 998, 5, 241, 119, 2, 998, 999, 5, 211, 104, 2, 999, 1000, 5, 241, 119, 2, 1000, 1001, 5, 219, 108, 2, 1001, 1002, 5, 227, 112, 2, 1002, 1003, 5, 211, 104, 2, 1003, 1088, 3, 2, 2, 2, 1004, 1005, 5, 241, 119, 2, 1005, 1006, 5, 231, 114, 2, 1006, 1007, 5, 111, 54, 2, 1007, 1008, 5, 209, 103, 2, 1008, 1009, 5, 241, 119, 2, 1009, 1088, 3, 2, 2, 2, 1010, 1011, 5, 241, 119, 2, 1011, 1012, 5, 231, 114, 2, 1012, 1013, 5, 111, 54, 2, 1013, 1014, 5, 209, 103, 2, 1014, 1015, 5, 205, 101, 2, 1015, 1016, 5, 225, 111, 2, 1016, 1088, 3, 2, 2, 2, 1017, 1018, 5, 241, 119, 2, 1018, 1019, 5, 231, 114, 2, 1019, 1020, 5, 111, 54, 2, 1020, 1021, 5, 209, 103, 2, 1021, 1022, 5, 231, 114, 2, 1022, 1023, 5, 243, 120, 2, 1023, 1024, 5, 205, 101, 2, 1024, 1025, 5, 225, 111, 2, 1025, 1026, 5, 211, 104, 2, 1026, 1088, 3, 2, 2, 2, 1027, 1028, 5, 241, 119, 2, 1028, 1029, 5, 231, 114, 2, 1029, 1030, 5, 111, 54, 2, 1030, 1031, 5, 219, 108, 2, 1031, 1032, 5, 229, 113, 2, 1032, 1033, 5, 241, 119, 2, 1033, 1088, 3, 2, 2, 2, 1034, 1035, 5, 241, 119, 2, 1035, 1036, 5, 231, 114, 2, 1036, 1037, 5, 111, 54, 2, 1037, 1038, 5, 219, 108, 2, 1038, 1039, 5, 229, 113, 2, 1039, 1040, 5, 241, 119, 2, 1040, 1041, 5, 211, 104, 2, 1041, 1042, 5, 215, 106, 2, 1042, 1043, 5, 211, 104, 2, 1043, 1044, 5, 237, 117, 2, 1044, 1088, 3, 2, 2, 2, 1045, 1046, 5, 241, 119, 2, 1046, 1047, 5, 231, 114, 2, 1047, 1048, 5, 111, 54, 2, 1048, 1049, 5, 225, 111, 2, 1049, 1050, 5, 231, 114, 2, 1050, 1051, 5, 229, 113, 2, 1051, 1052, 5, 215, 106, 2, 1052, 1088, 3, 2, 2, 2, 1053, 1054, 5, 241, 119, 2, 1054, 1055, 5, 231, 114, 2, 1055, 1056, 5, 111, 54, 2, 1056, 1057, 5, 219, 108, 2, 1057, 1058, 5, 233, 115, 2, 1058, 1088, 3, 2, 2, 2, 1059, 1060, 5, 241, 119, 2, 1060, 1061, 5, 231, 114, 2, 1061, 1062, 5, 111, 54, 2, 1062, 1063, 5, 245, 121, 2, 1063, 1064, 5, 211, 104, 2, 1064, 1065, 5, 237, 117, 2, 1065, 1066, 5, 239, 118, 2, 1066, 1067, 5, 219, 108, 2, 1067, 1068, 5, 231, 114, 2, 1068, 1069, 5, 229, 113, 2, 1069, 1088, 3, 2, 2, 2, 1070, 1071, 5, 241, 119, 2, 1071, 1072, 5, 231, 114, 2, 1072, 1073, 5, 111, 54, 2, 1073, 1074, 5, 243, 120, 2, 1074, 1075, 5, 229, 113, 2, 1075, 1076, 5, 239, 118, 2, 1076, 1077, 5, 219, 108, 2, 1077, 1078, 5, 215, 106, 2, 1078, 1079, 5, 229, 113, 2, 1079, 1080, 5, 211, 104, 2, 1080, 1081, 5, 209, 103, 2, 1081, 1082, 5, 111, 54, 2, 1082, 1083, 5, 225, 111, 2, 1083, 1084, 5, 231, 114, 2, 1084, 1085, 5, 229, 113, 2, 1085, 1086, 5, 215, 106, 2, 1086, 1088, 3, 2, 2, 2, 1087, 725, 3, 2, 2, 2, 1087, 731, 3, 2, 2, 2, 1087, 735, 3, 2, 2, 2, 1087, 739, 3, 2, 2, 2, 1087, 744, 3, 2, 2, 2, 1087, 747, 3, 2, 2, 2, 1087, 751, 3, 2, 2, 2, 1087, 752, 3, 2, 2, 2, 1087, 762, 3, 2, 2, 2, 1087, 767, 3, 2, 2, 2, 1087, 774, 3, 2, 2, 2, 1087, 786, 3, 2, 2, 2, 1087, 798, 3, 2, 2, 2, 1087, 809, 3, 2, 2, 2, 1087, 820, 3, 2, 2, 2, 1087, 832, 3, 2, 2, 2, 1087, 842, 3, 2, 2, 2, 1087, 854, 3, 2, 2, 2, 1087, 859, 3, 2, 2, 2, 1087, 866, 3, 2, 2, 2, 1087, 873, 3, 2, 2, 2, 1087, 880, 3, 2, 2, 2, 1087, 887, 3, 2, 2, 2, 1087, 894, 3, 2, 2, 2, 1087, 903, 3, 2, 2, 2, 1087, 913, 3, 2, 2, 2, 1087, 921, 3, 2, 2, 2, 1087, 931, 3, 2, 2, 2, 1087, 941, 3, 2, 2, 2, 1087, 950, 3, 2, 2, 2, 1087, 956, 3, 2, 2, 2, 1087, 966, 3, 2, 2, 2, 1087, 973, 3, 2, 2, 2, 1087, 981, 3, 2, 2, 2, 1087, 992, 3, 2, 2, 2, 1087, 1004, 3, 2, 2, 2, 1087, 1010, 3, 2, 2, 2, 1087, 1017, 3, 2, 2, 2, 1087, 1027, 3, 2, 2, 2, 1087, 1034, 3, 2, 2, 2, 1087, 1045, 3, 2, 2, 2, 1087, 1053, 3, 2, 2, 2, 1087, 1059, 3, 2, 2, 2, 1087, 1070, 3, 2, 2, 2, 1088, 140, 3, 2, 2, 2, 1089, 1090, 5, 203, 100, 2, 1090, 1091, 5, 245, 121, 2, 1091, 1092, 5, 215, 106, 2, 1092, 1171, 3, 2, 2, 2, 1093, 1094, 5, 227, 112, 2, 1094, 1095, 5, 219, 108, 2, 1095, 1096, 5, 229, 113, 2, 1096, 1171, 3, 2, 2, 2, 1097, 1098, 5, 227, 112, 2, 1098, 1099, 5, 203, 100, 2, 1099, 1100, 5, 249, 123, 2, 1100, 1171, 3, 2, 2, 2, 1101, 1102, 5, 239, 118, 2, 1102, 1103, 5, 243, 120, 2, 1103, 1104, 5, 227, 112, 2, 1104, 1171, 3, 2, 2, 2, 1105, 1106, 5, 207, 102, 2, 1106, 1107, 5, 231, 114, 2, 1107, 1108, 5, 243, 120, 2, 1108, 1109, 5, 229, 113, 2, 1109, 1110, 5, 241, 119, 2, 1110, 1171, 3, 2, 2, 2, 1111, 1112, 5, 207, 102, 2, 1112, 1113, 5, 231, 114, 2, 1113, 1114, 5, 243, 120, 2, 1114, 1115, 5, 229, 113, 2, 1115, 1116, 5, 241, 119, 2, 1116, 1117, 5, 111, 54, 2, 1117, 1118, 5, 209, 103, 2, 1118, 1119, 5, 219, 108, 2, 1119, 1120, 5, 239, 118, 2, 1120, 1121, 5, 241, 119, 2, 1121, 1122, 5, 219, 108, 2, 1122, 1123, 5, 229, 113, 2, 1123, 1124, 5, 207, 102, 2, 1124, 1125, 5, 241, 119, 2, 1125, 1171, 3, 2, 2, 2, 1126, 1127, 5, 233, 115, 2, 1127, 1128, 5, 211, 104, 2, 1128, 1129, 5, 237, 117, 2, 1129, 1130, 5, 207, 102, 2, 1130, 1131, 5, 211, 104, 2, 1131, 1132, 5, 229, 113, 2, 1132, 1133, 5, 241, 119, 2, 1133, 1134, 5, 219, 108, 2, 1134, 1135, 5, 225, 111, 2, 1135, 1136, 5, 211, 104, 2, 1136, 1171, 3, 2, 2, 2, 1137, 1138, 5, 227, 112, 2, 1138, 1139, 5, 211, 104, 2, 1139, 1140, 5, 209, 103, 2, 1140, 1141, 5, 219, 108, 2, 1141, 1142, 5, 203, 100, 2, 1142, 1143, 5, 229, 113, 2, 1143, 1171, 3, 2, 2, 2, 1144, 1145, 5, 227, 112, 2, 1145, 1146, 5, 211, 104, 2, 1146, 1147, 5, 209, 103, 2, 1147, 1148, 5, 219, 108, 2, 1148, 1149, 5, 203, 100, 2, 1149, 1150, 5, 229, 113, 2, 1150, 1151, 5, 111, 54, 2, 1151, 1152, 5, 203, 100, 2, 1152, 1153, 5, 205, 101, 2, 1153, 1154, 5, 239, 118, 2, 1154, 1155, 5, 231, 114, 2, 1155, 1156, 5, 225, 111, 2, 1156, 1157, 5, 243, 120, 2, 1157, 1158, 5, 241, 119, 2, 1158, 1159, 5, 211, 104, 2, 1159, 1160, 5, 111, 54, 2, 1160, 1161, 5, 209, 103, 2, 1161, 1162, 5, 211, 104, 2, 1162, 1163, 5, 245, 121, 2, 1163, 1164, 5, 219, 108, 2, 1164, 1165, 5, 203, 100, 2, 1165, 1166, 5, 241, 119, 2, 1166, 1167, 5, 219, 108, 2, 1167, 1168, 5, 231, 114, 2, 1168, 1169, 5, 229, 113, 2, 1169, 1171, 3, 2, 2, 2, 1170, 1089, 3, 2, 2, 2, 1170, 1093, 3, 2, 2, 2, 1170, 1097, 3, 2, 2, 2, 1170, 1101, 3, 2, 2, 2, 1170, 1105, 3, 2, 2, 2, 1170, 1111, 3, 2, 2, 2, 1170, 1126, 3, 2, 2, 2, 1170, 1137, 3, 2, 2, 2, 1170, 1144, 3, 2, 2, 2, 1171, 142, 3, 2, 2, 2, 1172, 1173, 5, 207, 102, 2, 1173, 1174, 5, 219, 108, 2, 1174, 1175, 5, 209, 103, 2, 1175, 1176, 5, 237, 117, 2, 1176, 1177, 5, 111, 54, 2, 1177, 1178, 5, 227, 112, 2, 1178, 1179, 5, 203, 100, 2, 1179, 1180, 5, 241, 119, 2, 1180, 1181, 5, 207, 102, 2, 1181, 1182, 5, 217, 107, 2, 1182, 144, 3, 2, 2, 2, 1183, 1190, 5, 61, 29, 2, 1184, 1189, 5, 61, 29, 2, 1185, 1189, 5, 59, 28, 2, 1186, 1189, 7, 97, 2, 2, 1187, 1189, 5, 125, 61, 2, 1188, 1184, 3, 2, 2, 2, 1188, 1185, 3, 2, 2, 2, 1188, 1186, 3, 2, 2, 2, 1188, 1187, 3, 2, 2, 2, 1189, 1192, 3, 2, 2, 2, 1190, 1188, 3, 2, 2, 2, 1190, 1191, 3, 2, 2, 2, 1191, 1203, 3, 2, 2, 2, 1192, 1190, 3, 2, 2, 2, 1193, 1198, 9, 10, 2, 2, 1194, 1199, 5, 61, 29, 2, 1195, 1199, 5, 59, 28, 2, 1196, 1199, 7, 97, 2, 2, 1197, 1199, 5, 125, 61, 2, 1198, 1194, 3, 2, 2, 2, 1198, 1195, 3, 2, 2, 2, 1198, 1196, 3, 2, 2, 2, 1198, 1197, 3, 2, 2, 2, 1199, 1200, 3, 2, 2, 2, 1200, 1198, 3, 2, 2, 2, 1200, 1201, 3, 2, 2, 2, 1201, 1203, 3, 2, 2, 2, 1202, 1183, 3, 2, 2, 2, 1202, 1193, 3, 2, 2, 2, 1203, 146, 3, 2, 2, 2, 1204, 1210, 7, 98, 2, 2, 1205, 1209, 10, 11, 2, 2, 1206, 1207, 7, 98, 2, 2, 1207, 1209, 7, 98, 2, 2, 1208, 1205, 3, 2, 2, 2, 1208, 1206, 3, 2, 2, 2, 1209, 1212, 3, 2, 2, 2, 1210, 1208, 3, 2, 2, 2, 1210, 1211, 3, 2, 2, 2, 1211, 1213, 3, 2, 2, 2, 1212, 1210, 3, 2, 2, 2, 1213, 1214, 7, 98, 2, 2, 1214, 148, 3, 2, 2, 2, 1215, 1216, 5, 41, 19, 2, 1216, 1217, 3, 2, 2, 2, 1217, 1218, 8, 73, 6, 2, 1218, 150, 3, 2, 2, 2, 1219, 1220, 5, 43, 20, 2, 1220, 1221, 3, 2, 2, 2, 1221, 1222, 8, 74, 6, 2, 1222, 152, 3, 2, 2, 2, 1223, 1224, 5, 45, 21, 2, 1224, 1225, 3, 2, 2, 2, 1225, 1226, 8, 75, 6, 2, 1226, 154, 3, 2, 2, 2, 1227, 1228, 7, 126, 2, 2, 1228, 1229, 3, 2, 2, 2, 1229, 1230, 8, 76, 9, 2, 1230, 1231, 8, 76, 10, 2, 1231, 156, 3, 2, 2, 2, 1232, 1233, 7, 93, 2, 2, 1233, 1234, 3, 2, 2, 2, 1234, 1235, 8, 77, 7, 2, 1235, 1236, 8, 77, 4, 2, 1236, 1237, 8, 77, 4, 2, 1237, 158, 3, 2, 2, 2, 1238, 1239, 7, 95, 2, 2, 1239, 1240, 3, 2, 2, 2, 1240, 1241, 8, 78, 10, 2, 1241, 1242, 8, 78, 10, 2, 1242, 1243, 8, 78, 11, 2, 1243, 160, 3, 2, 2, 2, 1244, 1245, 7, 46, 2, 2, 1245, 1246, 3, 2, 2, 2, 1246, 1247, 8, 79, 12, 2, 1247, 162, 3, 2, 2, 2, 1248, 1249, 7, 63, 2, 2, 1249, 1250, 3, 2, 2, 2, 1250, 1251, 8, 80, 13, 2, 1251, 164, 3, 2, 2, 2, 1252, 1253, 5, 227, 112, 2, 1253, 1254, 5, 211, 104, 2, 1254, 1255, 5, 241, 119, 2, 1255, 1256, 5, 203, 100, 2, 1256, 1257, 5, 209, 103, 2, 1257, 1258, 5, 203, 100, 2, 1258, 1259, 5, 241, 119, 2, 1259, 1260, 5, 203, 100, 2, 1260, 166, 3, 2, 2, 2, 1261, 1263, 5, 169, 83, 2, 1262, 1261, 3, 2, 2, 2, 1263, 1264, 3, 2, 2, 2, 1264, 1262, 3, 2, 2, 2, 1264, 1265, 3, 2, 2, 2, 1265, 168, 3, 2, 2, 2, 1266, 1268, 10, 12, 2, 2, 1267, 1266, 3, 2, 2, 2, 1268, 1269, 3, 2, 2, 2, 1269, 1267, 3, 2, 2, 2, 1269, 1270, 3, 2, 2, 2, 1270, 1274, 3, 2, 2, 2, 1271, 1272, 7, 49, 2, 2, 1272, 1274, 10, 13, 2, 2, 1273, 1267, 3, 2, 2, 2, 1273, 1271, 3, 2, 2, 2, 1274, 170, 3, 2, 2, 2, 1275, 1276, 5, 147, 72, 2, 1276, 172, 3, 2, 2, 2, 1277, 1278, 5, 41, 19, 2, 1278, 1279, 3, 2, 2, 2, 1279, 1280, 8, 85, 6, 2, 1280, 174, 3, 2, 2, 2, 1281, 1282, 5, 43, 20, 2, 1282, 1283, 3, 2, 2, 2, 1283, 1284, 8, 86, 6, 2, 1284, 176, 3, 2, 2, 2, 1285, 1286, 5, 45, 21, 2, 1286, 1287, 3, 2, 2, 2, 1287, 1288, 8, 87, 6, 2, 1288, 178, 3, 2, 2, 2, 1289, 1290, 5, 231, 114, 2, 1290, 1291, 5, 229, 113, 2, 1291, 180, 3, 2, 2, 2, 1292, 1293, 5, 247, 122, 2, 1293, 1294, 5, 219, 108, 2, 1294, 1295, 5, 241, 119, 2, 1295, 1296, 5, 217, 107, 2, 1296, 182, 3, 2, 2, 2, 1297, 1298, 7, 126, 2, 2, 1298, 1299, 3, 2, 2, 2, 1299, 1300, 8, 90, 9, 2, 1300, 1301, 8, 90, 10, 2, 1301, 184, 3, 2, 2, 2, 1302, 1303, 7, 95, 2, 2, 1303, 1304, 3, 2, 2, 2, 1304, 1305, 8, 91, 10, 2, 1305, 1306, 8, 91, 10, 2, 1306, 1307, 8, 91, 11, 2, 1307, 186, 3, 2, 2, 2, 1308, 1309, 7, 46, 2, 2, 1309, 1310, 3, 2, 2, 2, 1310, 1311, 8, 92, 12, 2, 1311, 188, 3, 2, 2, 2, 1312, 1313, 7, 63, 2, 2, 1313, 1314, 3, 2, 2, 2, 1314, 1315, 8, 93, 13, 2, 1315, 190, 3, 2, 2, 2, 1316, 1318, 5, 193, 95, 2, 1317, 1316, 3, 2, 2, 2, 1318, 1319, 3, 2, 2, 2, 1319, 1317, 3, 2, 2, 2, 1319, 1320, 3, 2, 2, 2, 1320, 192, 3, 2, 2, 2, 1321, 1323, 10, 12, 2, 2, 1322, 1321, 3, 2, 2, 2, 1323, 1324, 3, 2, 2, 2, 1324, 1322, 3, 2, 2, 2, 1324, 1325, 3, 2, 2, 2, 1325, 1329, 3, 2, 2, 2, 1326, 1327, 7, 49, 2, 2, 1327, 1329, 10, 13, 2, 2, 1328, 1322, 3, 2, 2, 2, 1328, 1326, 3, 2, 2, 2, 1329, 194, 3, 2, 2, 2, 1330, 1331, 5, 147, 72, 2, 1331, 196, 3, 2, 2, 2, 1332, 1333, 5, 41, 19, 2, 1333, 1334, 3, 2, 2, 2, 1334, 1335, 8, 97, 6, 2, 1335, 198, 3, 2, 2, 2, 1336, 1337, 5, 43, 20, 2, 1337, 1338, 3, 2, 2, 2, 1338, 1339, 8, 98, 6, 2, 1339, 200, 3, 2, 2, 2, 1340, 1341, 5, 45, 21, 2, 1341, 1342, 3, 2, 2, 2, 1342, 1343, 8, 99, 6, 2, 1343, 202, 3, 2, 2, 2, 1344, 1345, 9, 14, 2, 2, 1345, 204, 3, 2, 2, 2, 1346, 1347, 9, 15, 2, 2, 1347, 206, 3, 2, 2, 2, 1348, 1349, 9, 16, 2, 2, 1349, 208, 3, 2, 2, 2, 1350, 1351, 9, 17, 2, 2, 1351, 210, 3, 2, 2, 2, 1352, 1353, 9, 8, 2, 2, 1353, 212, 3, 2, 2, 2, 1354, 1355, 9, 18, 2, 2, 1355, 214, 3, 2, 2, 2, 1356, 1357, 9, 19, 2, 2, 1357, 216, 3, 2, 2, 2, 1358, 1359, 9, 20, 2, 2, 1359, 218, 3, 2, 2, 2, 1360, 1361, 9, 21, 2, 2, 1361, 220, 3, 2, 2, 2, 1362, 1363, 9, 22, 2, 2, 1363, 222, 3, 2, 2, 2, 1364, 1365, 9, 23, 2, 2, 1365, 224, 3, 2, 2, 2, 1366, 1367, 9, 24, 2, 2, 1367, 226, 3, 2, 2, 2, 1368, 1369, 9, 25, 2, 2, 1369, 228, 3, 2, 2, 2, 1370, 1371, 9, 26, 2, 2, 1371, 230, 3, 2, 2, 2, 1372, 1373, 9, 27, 2, 2, 1373, 232, 3, 2, 2, 2, 1374, 1375, 9, 28, 2, 2, 1375, 234, 3, 2, 2, 2, 1376, 1377, 9, 29, 2, 2, 1377, 236, 3, 2, 2, 2, 1378, 1379, 9, 30, 2, 2, 1379, 238, 3, 2, 2, 2, 1380, 1381, 9, 31, 2, 2, 1381, 240, 3, 2, 2, 2, 1382, 1383, 9, 32, 2, 2, 1383, 242, 3, 2, 2, 2, 1384, 1385, 9, 33, 2, 2, 1385, 244, 3, 2, 2, 2, 1386, 1387, 9, 34, 2, 2, 1387, 246, 3, 2, 2, 2, 1388, 1389, 9, 35, 2, 2, 1389, 248, 3, 2, 2, 2, 1390, 1391, 9, 36, 2, 2, 1391, 250, 3, 2, 2, 2, 1392, 1393, 9, 37, 2, 2, 1393, 252, 3, 2, 2, 2, 1394, 1395, 9, 38, 2, 2, 1395, 254, 3, 2, 2, 2, 50, 2, 3, 4, 5, 6, 400, 404, 407, 416, 418, 429, 470, 475, 480, 482, 493, 501, 504, 506, 511, 516, 522, 529, 534, 540, 543, 551, 555, 588, 672, 684, 706, 723, 1087, 1170, 1188, 1190, 1198, 1200, 1202, 1208, 1210, 1264, 1269, 1273, 1319, 1324, 1328, 14, 7, 4, 2, 7, 3, 2, 7, 5, 2, 7, 6, 2, 2, 3, 2, 9, 37, 2, 7, 2, 2, 9, 26, 2, 6, 2, 2, 9, 38, 2, 9, 34, 2, 9, 33, 2] \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens b/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens index c2dafff2f222c..b72e97b9a2961 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens @@ -1,74 +1,98 @@ -EVAL=1 -EXPLAIN=2 -FROM=3 -ROW=4 -STATS=5 -WHERE=6 -SORT=7 -LIMIT=8 -PROJECT=9 -LINE_COMMENT=10 -MULTILINE_COMMENT=11 -WS=12 -PIPE=13 -STRING=14 -INTEGER_LITERAL=15 -DECIMAL_LITERAL=16 -BY=17 -AND=18 -ASSIGN=19 -COMMA=20 -DOT=21 -LP=22 -OPENING_BRACKET=23 -CLOSING_BRACKET=24 -NOT=25 -NULL=26 -OR=27 -RP=28 -BOOLEAN_VALUE=29 -COMPARISON_OPERATOR=30 -PLUS=31 -MINUS=32 -ASTERISK=33 -SLASH=34 -PERCENT=35 -ORDERING=36 -NULLS_ORDERING=37 -NULLS_ORDERING_DIRECTION=38 -UNARY_FUNCTION=39 -UNQUOTED_IDENTIFIER=40 -QUOTED_IDENTIFIER=41 -EXPR_LINE_COMMENT=42 -EXPR_MULTILINE_COMMENT=43 -EXPR_WS=44 -SRC_UNQUOTED_IDENTIFIER=45 -SRC_QUOTED_IDENTIFIER=46 -SRC_LINE_COMMENT=47 -SRC_MULTILINE_COMMENT=48 -SRC_WS=49 -'eval'=1 -'explain'=2 -'from'=3 -'row'=4 -'stats'=5 -'where'=6 -'sort'=7 -'limit'=8 -'project'=9 -'by'=17 -'and'=18 -'.'=21 -'('=22 -'['=23 -']'=24 -'not'=25 -'null'=26 -'or'=27 -')'=28 -'+'=31 -'-'=32 -'*'=33 -'/'=34 -'%'=35 -'nulls'=37 +DISSECT=1 +GROK=2 +EVAL=3 +EXPLAIN=4 +FROM=5 +ROW=6 +STATS=7 +WHERE=8 +SORT=9 +MV_EXPAND=10 +LIMIT=11 +PROJECT=12 +DROP=13 +RENAME=14 +SHOW=15 +ENRICH=16 +KEEP=17 +LINE_COMMENT=18 +MULTILINE_COMMENT=19 +WS=20 +EXPLAIN_WS=21 +EXPLAIN_LINE_COMMENT=22 +EXPLAIN_MULTILINE_COMMENT=23 +PIPE=24 +STRING=25 +INTEGER_LITERAL=26 +DECIMAL_LITERAL=27 +BY=28 +DATE_LITERAL=29 +AND=30 +ASSIGN=31 +COMMA=32 +DOT=33 +LP=34 +OPENING_BRACKET=35 +CLOSING_BRACKET=36 +NOT=37 +LIKE=38 +RLIKE=39 +IN=40 +IS=41 +AS=42 +NULL=43 +OR=44 +RP=45 +UNDERSCORE=46 +INFO=47 +FUNCTIONS=48 +BOOLEAN_VALUE=49 +COMPARISON_OPERATOR=50 +PLUS=51 +MINUS=52 +ASTERISK=53 +SLASH=54 +PERCENT=55 +TEN=56 +ORDERING=57 +NULLS_ORDERING=58 +NULLS_ORDERING_DIRECTION=59 +MATH_FUNCTION=60 +UNARY_FUNCTION=61 +WHERE_FUNCTIONS=62 +UNQUOTED_IDENTIFIER=63 +QUOTED_IDENTIFIER=64 +EXPR_LINE_COMMENT=65 +EXPR_MULTILINE_COMMENT=66 +EXPR_WS=67 +METADATA=68 +SRC_UNQUOTED_IDENTIFIER=69 +SRC_QUOTED_IDENTIFIER=70 +SRC_LINE_COMMENT=71 +SRC_MULTILINE_COMMENT=72 +SRC_WS=73 +ON=74 +WITH=75 +ENR_UNQUOTED_IDENTIFIER=76 +ENR_QUOTED_IDENTIFIER=77 +ENR_LINE_COMMENT=78 +ENR_MULTILINE_COMMENT=79 +ENR_WS=80 +EXPLAIN_PIPE=81 +'by'=28 +'and'=30 +'.'=33 +'('=34 +']'=36 +'or'=44 +')'=45 +'_'=46 +'info'=47 +'functions'=48 +'+'=51 +'-'=52 +'*'=53 +'/'=54 +'%'=55 +'10'=56 +'nulls'=58 diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts b/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts index 064b2fe2c02d1..6d8ddeb0f848e 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts @@ -17,57 +17,91 @@ import * as Utils from "antlr4ts/misc/Utils"; export class esql_lexer extends Lexer { - public static readonly EVAL = 1; - public static readonly EXPLAIN = 2; - public static readonly FROM = 3; - public static readonly ROW = 4; - public static readonly STATS = 5; - public static readonly WHERE = 6; - public static readonly SORT = 7; - public static readonly LIMIT = 8; - public static readonly PROJECT = 9; - public static readonly LINE_COMMENT = 10; - public static readonly MULTILINE_COMMENT = 11; - public static readonly WS = 12; - public static readonly PIPE = 13; - public static readonly STRING = 14; - public static readonly INTEGER_LITERAL = 15; - public static readonly DECIMAL_LITERAL = 16; - public static readonly BY = 17; - public static readonly AND = 18; - public static readonly ASSIGN = 19; - public static readonly COMMA = 20; - public static readonly DOT = 21; - public static readonly LP = 22; - public static readonly OPENING_BRACKET = 23; - public static readonly CLOSING_BRACKET = 24; - public static readonly NOT = 25; - public static readonly NULL = 26; - public static readonly OR = 27; - public static readonly RP = 28; - public static readonly BOOLEAN_VALUE = 29; - public static readonly COMPARISON_OPERATOR = 30; - public static readonly PLUS = 31; - public static readonly MINUS = 32; - public static readonly ASTERISK = 33; - public static readonly SLASH = 34; - public static readonly PERCENT = 35; - public static readonly ORDERING = 36; - public static readonly NULLS_ORDERING = 37; - public static readonly NULLS_ORDERING_DIRECTION = 38; - public static readonly UNARY_FUNCTION = 39; - public static readonly UNQUOTED_IDENTIFIER = 40; - public static readonly QUOTED_IDENTIFIER = 41; - public static readonly EXPR_LINE_COMMENT = 42; - public static readonly EXPR_MULTILINE_COMMENT = 43; - public static readonly EXPR_WS = 44; - public static readonly SRC_UNQUOTED_IDENTIFIER = 45; - public static readonly SRC_QUOTED_IDENTIFIER = 46; - public static readonly SRC_LINE_COMMENT = 47; - public static readonly SRC_MULTILINE_COMMENT = 48; - public static readonly SRC_WS = 49; - public static readonly EXPRESSION = 1; - public static readonly SOURCE_IDENTIFIERS = 2; + public static readonly DISSECT = 1; + public static readonly GROK = 2; + public static readonly EVAL = 3; + public static readonly EXPLAIN = 4; + public static readonly FROM = 5; + public static readonly ROW = 6; + public static readonly STATS = 7; + public static readonly WHERE = 8; + public static readonly SORT = 9; + public static readonly MV_EXPAND = 10; + public static readonly LIMIT = 11; + public static readonly PROJECT = 12; + public static readonly DROP = 13; + public static readonly RENAME = 14; + public static readonly SHOW = 15; + public static readonly ENRICH = 16; + public static readonly KEEP = 17; + public static readonly LINE_COMMENT = 18; + public static readonly MULTILINE_COMMENT = 19; + public static readonly WS = 20; + public static readonly EXPLAIN_WS = 21; + public static readonly EXPLAIN_LINE_COMMENT = 22; + public static readonly EXPLAIN_MULTILINE_COMMENT = 23; + public static readonly PIPE = 24; + public static readonly STRING = 25; + public static readonly INTEGER_LITERAL = 26; + public static readonly DECIMAL_LITERAL = 27; + public static readonly BY = 28; + public static readonly DATE_LITERAL = 29; + public static readonly AND = 30; + public static readonly ASSIGN = 31; + public static readonly COMMA = 32; + public static readonly DOT = 33; + public static readonly LP = 34; + public static readonly OPENING_BRACKET = 35; + public static readonly CLOSING_BRACKET = 36; + public static readonly NOT = 37; + public static readonly LIKE = 38; + public static readonly RLIKE = 39; + public static readonly IN = 40; + public static readonly IS = 41; + public static readonly AS = 42; + public static readonly NULL = 43; + public static readonly OR = 44; + public static readonly RP = 45; + public static readonly UNDERSCORE = 46; + public static readonly INFO = 47; + public static readonly FUNCTIONS = 48; + public static readonly BOOLEAN_VALUE = 49; + public static readonly COMPARISON_OPERATOR = 50; + public static readonly PLUS = 51; + public static readonly MINUS = 52; + public static readonly ASTERISK = 53; + public static readonly SLASH = 54; + public static readonly PERCENT = 55; + public static readonly TEN = 56; + public static readonly ORDERING = 57; + public static readonly NULLS_ORDERING = 58; + public static readonly NULLS_ORDERING_DIRECTION = 59; + public static readonly MATH_FUNCTION = 60; + public static readonly UNARY_FUNCTION = 61; + public static readonly WHERE_FUNCTIONS = 62; + public static readonly UNQUOTED_IDENTIFIER = 63; + public static readonly QUOTED_IDENTIFIER = 64; + public static readonly EXPR_LINE_COMMENT = 65; + public static readonly EXPR_MULTILINE_COMMENT = 66; + public static readonly EXPR_WS = 67; + public static readonly METADATA = 68; + public static readonly SRC_UNQUOTED_IDENTIFIER = 69; + public static readonly SRC_QUOTED_IDENTIFIER = 70; + public static readonly SRC_LINE_COMMENT = 71; + public static readonly SRC_MULTILINE_COMMENT = 72; + public static readonly SRC_WS = 73; + public static readonly ON = 74; + public static readonly WITH = 75; + public static readonly ENR_UNQUOTED_IDENTIFIER = 76; + public static readonly ENR_QUOTED_IDENTIFIER = 77; + public static readonly ENR_LINE_COMMENT = 78; + public static readonly ENR_MULTILINE_COMMENT = 79; + public static readonly ENR_WS = 80; + public static readonly EXPLAIN_PIPE = 81; + public static readonly EXPLAIN_MODE = 1; + public static readonly EXPRESSION = 2; + public static readonly SOURCE_IDENTIFIERS = 3; + public static readonly ENRICH_IDENTIFIERS = 4; // tslint:disable:no-trailing-whitespace public static readonly channelNames: string[] = [ @@ -76,40 +110,58 @@ export class esql_lexer extends Lexer { // tslint:disable:no-trailing-whitespace public static readonly modeNames: string[] = [ - "DEFAULT_MODE", "EXPRESSION", "SOURCE_IDENTIFIERS", + "DEFAULT_MODE", "EXPLAIN_MODE", "EXPRESSION", "SOURCE_IDENTIFIERS", "ENRICH_IDENTIFIERS", ]; public static readonly ruleNames: string[] = [ - "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", "WHERE", "SORT", "LIMIT", "PROJECT", - "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", "DIGIT", "LETTER", - "ESCAPE_SEQUENCE", "UNESCAPED_CHARS", "EXPONENT", "STRING", "INTEGER_LITERAL", - "DECIMAL_LITERAL", "BY", "AND", "ASSIGN", "COMMA", "DOT", "LP", "OPENING_BRACKET", - "CLOSING_BRACKET", "NOT", "NULL", "OR", "RP", "BOOLEAN_VALUE", "COMPARISON_OPERATOR", - "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", "ORDERING", "NULLS_ORDERING", - "NULLS_ORDERING_DIRECTION", "UNARY_FUNCTION", "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", - "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", "SRC_PIPE", - "SRC_CLOSING_BRACKET", "SRC_COMMA", "SRC_ASSIGN", "SRC_UNQUOTED_IDENTIFIER", - "SRC_UNQUOTED_IDENTIFIER_PART", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", - "SRC_MULTILINE_COMMENT", "SRC_WS", + "DISSECT", "GROK", "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", "WHERE", + "SORT", "MV_EXPAND", "LIMIT", "PROJECT", "DROP", "RENAME", "SHOW", "ENRICH", + "KEEP", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "EXPLAIN_OPENING_BRACKET", + "EXPLAIN_PIPE", "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", + "PIPE", "DIGIT", "LETTER", "ESCAPE_SEQUENCE", "UNESCAPED_CHARS", "EXPONENT", + "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "DATE_LITERAL", + "AND", "ASSIGN", "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", + "NOT", "LIKE", "RLIKE", "IN", "IS", "AS", "NULL", "OR", "RP", "UNDERSCORE", + "INFO", "FUNCTIONS", "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", + "ASTERISK", "SLASH", "PERCENT", "TEN", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", + "MATH_FUNCTION", "UNARY_FUNCTION", "WHERE_FUNCTIONS", "UNQUOTED_IDENTIFIER", + "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", + "SRC_PIPE", "SRC_OPENING_BRACKET", "SRC_CLOSING_BRACKET", "SRC_COMMA", + "SRC_ASSIGN", "METADATA", "SRC_UNQUOTED_IDENTIFIER", "SRC_UNQUOTED_IDENTIFIER_PART", + "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", + "SRC_WS", "ON", "WITH", "ENR_PIPE", "ENR_CLOSING_BRACKET", "ENR_COMMA", + "ENR_ASSIGN", "ENR_UNQUOTED_IDENTIFIER", "ENR_UNQUOTED_IDENTIFIER_PART", + "ENR_QUOTED_IDENTIFIER", "ENR_LINE_COMMENT", "ENR_MULTILINE_COMMENT", + "ENR_WS", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", + "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", ]; private static readonly _LITERAL_NAMES: Array = [ - undefined, "'eval'", "'explain'", "'from'", "'row'", "'stats'", "'where'", - "'sort'", "'limit'", "'project'", undefined, undefined, undefined, undefined, - undefined, undefined, undefined, "'by'", "'and'", undefined, undefined, - "'.'", "'('", "'['", "']'", "'not'", "'null'", "'or'", "')'", undefined, - undefined, "'+'", "'-'", "'*'", "'/'", "'%'", undefined, "'nulls'", + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + "'by'", undefined, "'and'", undefined, undefined, "'.'", "'('", undefined, + "']'", undefined, undefined, undefined, undefined, undefined, undefined, + undefined, "'or'", "')'", "'_'", "'info'", "'functions'", undefined, undefined, + "'+'", "'-'", "'*'", "'/'", "'%'", "'10'", undefined, "'nulls'", ]; private static readonly _SYMBOLIC_NAMES: Array = [ - undefined, "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", "WHERE", "SORT", - "LIMIT", "PROJECT", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", - "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASSIGN", - "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", "NOT", "NULL", - "OR", "RP", "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", "ASTERISK", - "SLASH", "PERCENT", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", - "UNARY_FUNCTION", "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", - "EXPR_MULTILINE_COMMENT", "EXPR_WS", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", - "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", "SRC_WS", + undefined, "DISSECT", "GROK", "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", + "WHERE", "SORT", "MV_EXPAND", "LIMIT", "PROJECT", "DROP", "RENAME", "SHOW", + "ENRICH", "KEEP", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "EXPLAIN_WS", + "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "PIPE", "STRING", + "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "DATE_LITERAL", "AND", "ASSIGN", + "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", "NOT", "LIKE", + "RLIKE", "IN", "IS", "AS", "NULL", "OR", "RP", "UNDERSCORE", "INFO", "FUNCTIONS", + "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", "ASTERISK", "SLASH", + "PERCENT", "TEN", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", + "MATH_FUNCTION", "UNARY_FUNCTION", "WHERE_FUNCTIONS", "UNQUOTED_IDENTIFIER", + "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", + "METADATA", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", + "SRC_MULTILINE_COMMENT", "SRC_WS", "ON", "WITH", "ENR_UNQUOTED_IDENTIFIER", + "ENR_QUOTED_IDENTIFIER", "ENR_LINE_COMMENT", "ENR_MULTILINE_COMMENT", + "ENR_WS", "EXPLAIN_PIPE", ]; public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(esql_lexer._LITERAL_NAMES, esql_lexer._SYMBOLIC_NAMES, []); @@ -141,266 +193,682 @@ export class esql_lexer extends Lexer { // @Override public get modeNames(): string[] { return esql_lexer.modeNames; } - public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x023\u0215\b\x01" + - "\b\x01\b\x01\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04" + - "\x06\t\x06\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f" + - "\t\f\x04\r\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11" + - "\x04\x12\t\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16" + - "\x04\x17\t\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B" + - "\x04\x1C\t\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!" + - "\t!\x04\"\t\"\x04#\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x04)\t" + - ")\x04*\t*\x04+\t+\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x040\t0\x041\t1\x04" + - "2\t2\x043\t3\x044\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04:\t:\x04" + - ";\t;\x04<\t<\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03" + - "\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03" + - "\x06\x03\x06\x03\x06\x03\x06\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03" + - "\x07\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\t\x03" + - "\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03" + - "\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03\v\x03\v\x07\v\xC7\n\v\f\v\x0E" + - "\v\xCA\v\v\x03\v\x05\v\xCD\n\v\x03\v\x05\v\xD0\n\v\x03\v\x03\v\x03\f\x03" + - "\f\x03\f\x03\f\x03\f\x07\f\xD9\n\f\f\f\x0E\f\xDC\v\f\x03\f\x03\f\x03\f" + - "\x03\f\x03\f\x03\r\x06\r\xE4\n\r\r\r\x0E\r\xE5\x03\r\x03\r\x03\x0E\x03" + - "\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x10\x03\x10\x03\x11\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x13\x03\x13\x05\x13\xF9\n\x13\x03\x13\x06\x13" + - "\xFC\n\x13\r\x13\x0E\x13\xFD\x03\x14\x03\x14\x03\x14\x07\x14\u0103\n\x14" + - "\f\x14\x0E\x14\u0106\v\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03" + - "\x14\x07\x14\u010E\n\x14\f\x14\x0E\x14\u0111\v\x14\x03\x14\x03\x14\x03" + - "\x14\x03\x14\x03\x14\x05\x14\u0118\n\x14\x03\x14\x05\x14\u011B\n\x14\x05" + - "\x14\u011D\n\x14\x03\x15\x06\x15\u0120\n\x15\r\x15\x0E\x15\u0121\x03\x16" + - "\x06\x16\u0125\n\x16\r\x16\x0E\x16\u0126\x03\x16\x03\x16\x07\x16\u012B" + - "\n\x16\f\x16\x0E\x16\u012E\v\x16\x03\x16\x03\x16\x06\x16\u0132\n\x16\r" + - "\x16\x0E\x16\u0133\x03\x16\x06\x16\u0137\n\x16\r\x16\x0E\x16\u0138\x03" + - "\x16\x03\x16\x07\x16\u013D\n\x16\f\x16\x0E\x16\u0140\v\x16\x05\x16\u0142" + - "\n\x16\x03\x16\x03\x16\x03\x16\x03\x16\x06\x16\u0148\n\x16\r\x16\x0E\x16" + - "\u0149\x03\x16\x03\x16\x05\x16\u014E\n\x16\x03\x17\x03\x17\x03\x17\x03" + - "\x18\x03\x18\x03\x18\x03\x18\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1B\x03" + - "\x1B\x03\x1C\x03\x1C\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03" + - "\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x03 \x03 \x03 \x03" + - " \x03 \x03!\x03!\x03!\x03\"\x03\"\x03#\x03#\x03#\x03#\x03#\x03#\x03#\x03" + - "#\x03#\x05#\u017F\n#\x03$\x03$\x03$\x03$\x03$\x03$\x03$\x03$\x03$\x03" + - "$\x05$\u018B\n$\x03%\x03%\x03&\x03&\x03\'\x03\'\x03(\x03(\x03)\x03)\x03" + - "*\x03*\x03*\x03*\x03*\x03*\x03*\x05*\u019E\n*\x03+\x03+\x03+\x03+\x03" + - "+\x03+\x03,\x03,\x03,\x03,\x03,\x03,\x03,\x03,\x03,\x05,\u01AF\n,\x03" + - "-\x03-\x03-\x03-\x03-\x03-\x03-\x03-\x03-\x03-\x03-\x03-\x03-\x03-\x03" + - "-\x03-\x03-\x05-\u01C2\n-\x03.\x03.\x05.\u01C6\n.\x03.\x03.\x03.\x07." + - "\u01CB\n.\f.\x0E.\u01CE\v.\x03/\x03/\x03/\x03/\x07/\u01D4\n/\f/\x0E/\u01D7" + - "\v/\x03/\x03/\x030\x030\x030\x030\x031\x031\x031\x031\x032\x032\x032\x03" + - "2\x033\x033\x033\x033\x033\x034\x034\x034\x034\x034\x034\x035\x035\x03" + - "5\x035\x036\x036\x036\x036\x037\x067\u01FB\n7\r7\x0E7\u01FC\x038\x068" + - "\u0200\n8\r8\x0E8\u0201\x038\x038\x058\u0206\n8\x039\x039\x03:\x03:\x03" + - ":\x03:\x03;\x03;\x03;\x03;\x03<\x03<\x03<\x03<\x04\xDA\u010F\x02\x02=" + - "\x05\x02\x03\x07\x02\x04\t\x02\x05\v\x02\x06\r\x02\x07\x0F\x02\b\x11\x02" + - "\t\x13\x02\n\x15\x02\v\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02\x0F\x1F" + - "\x02\x02!\x02\x02#\x02\x02%\x02\x02\'\x02\x02)\x02\x10+\x02\x11-\x02\x12" + - "/\x02\x131\x02\x143\x02\x155\x02\x167\x02\x179\x02\x18;\x02\x19=\x02\x1A" + - "?\x02\x1BA\x02\x1CC\x02\x1DE\x02\x1EG\x02\x1FI\x02 K\x02!M\x02\"O\x02" + - "#Q\x02$S\x02%U\x02&W\x02\'Y\x02([\x02)]\x02*_\x02+a\x02,c\x02-e\x02.g" + - "\x02\x02i\x02\x02k\x02\x02m\x02\x02o\x02/q\x02\x02s\x020u\x021w\x022y" + - "\x023\x05\x02\x03\x04\r\x04\x02\f\f\x0F\x0F\x05\x02\v\f\x0F\x0F\"\"\x03" + - "\x022;\x04\x02C\\c|\x07\x02$$^^ppttvv\x06\x02\f\f\x0F\x0F$$^^\x04\x02" + - "GGgg\x04\x02--//\x03\x02bb\f\x02\v\f\x0F\x0F\"\"..11??]]__bb~~\x04\x02" + - ",,11\x02\u023A\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03" + - "\x02\x02\x02\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02" + - "\x02\x02\x02\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x15\x03\x02" + - "\x02\x02\x02\x17\x03\x02\x02\x02\x02\x19\x03\x02\x02\x02\x02\x1B\x03\x02" + - "\x02\x02\x03\x1D\x03\x02\x02\x02\x03)\x03\x02\x02\x02\x03+\x03\x02\x02" + - "\x02\x03-\x03\x02\x02\x02\x03/\x03\x02\x02\x02\x031\x03\x02\x02\x02\x03" + - "3\x03\x02\x02\x02\x035\x03\x02\x02\x02\x037\x03\x02\x02\x02\x039\x03\x02" + - "\x02\x02\x03;\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x03?\x03\x02\x02\x02" + - "\x03A\x03\x02\x02\x02\x03C\x03\x02\x02\x02\x03E\x03\x02\x02\x02\x03G\x03" + - "\x02\x02\x02\x03I\x03\x02\x02\x02\x03K\x03\x02\x02\x02\x03M\x03\x02\x02" + - "\x02\x03O\x03\x02\x02\x02\x03Q\x03\x02\x02\x02\x03S\x03\x02\x02\x02\x03" + - "U\x03\x02\x02\x02\x03W\x03\x02\x02\x02\x03Y\x03\x02\x02\x02\x03[\x03\x02" + - "\x02\x02\x03]\x03\x02\x02\x02\x03_\x03\x02\x02\x02\x03a\x03\x02\x02\x02" + - "\x03c\x03\x02\x02\x02\x03e\x03\x02\x02\x02\x04g\x03\x02\x02\x02\x04i\x03" + - "\x02\x02\x02\x04k\x03\x02\x02\x02\x04m\x03\x02\x02\x02\x04o\x03\x02\x02" + - "\x02\x04s\x03\x02\x02\x02\x04u\x03\x02\x02\x02\x04w\x03\x02\x02\x02\x04" + - "y\x03\x02\x02\x02\x05{\x03\x02\x02\x02\x07\x82\x03\x02\x02\x02\t\x8C\x03" + - "\x02\x02\x02\v\x93\x03\x02\x02\x02\r\x99\x03\x02\x02\x02\x0F\xA1\x03\x02" + - "\x02\x02\x11\xA9\x03\x02\x02\x02\x13\xB0\x03\x02\x02\x02\x15\xB8\x03\x02" + - "\x02\x02\x17\xC2\x03\x02\x02\x02\x19\xD3\x03\x02\x02\x02\x1B\xE3\x03\x02" + - "\x02\x02\x1D\xE9\x03\x02\x02\x02\x1F\xED\x03\x02\x02\x02!\xEF\x03\x02" + - "\x02\x02#\xF1\x03\x02\x02\x02%\xF4\x03\x02\x02\x02\'\xF6\x03\x02\x02\x02" + - ")\u011C\x03\x02\x02\x02+\u011F\x03\x02\x02\x02-\u014D\x03\x02\x02\x02" + - "/\u014F\x03\x02\x02\x021\u0152\x03\x02\x02\x023\u0156\x03\x02\x02\x02" + - "5\u0158\x03\x02\x02\x027\u015A\x03\x02\x02\x029\u015C\x03\x02\x02\x02" + - ";\u015E\x03\x02\x02\x02=\u0162\x03\x02\x02\x02?\u0167\x03\x02\x02\x02" + - "A\u016B\x03\x02\x02\x02C\u0170\x03\x02\x02\x02E\u0173\x03\x02\x02\x02" + - "G\u017E\x03\x02\x02\x02I\u018A\x03\x02\x02\x02K\u018C\x03\x02\x02\x02" + - "M\u018E\x03\x02\x02\x02O\u0190\x03\x02\x02\x02Q\u0192\x03\x02\x02\x02" + - "S\u0194\x03\x02\x02\x02U\u019D\x03\x02\x02\x02W\u019F\x03\x02\x02\x02" + - "Y\u01AE\x03\x02\x02\x02[\u01C1\x03\x02\x02\x02]\u01C5\x03\x02\x02\x02" + - "_\u01CF\x03\x02\x02\x02a\u01DA\x03\x02\x02\x02c\u01DE\x03\x02\x02\x02" + - "e\u01E2\x03\x02\x02\x02g\u01E6\x03\x02\x02\x02i\u01EB\x03\x02\x02\x02" + - "k\u01F1\x03\x02\x02\x02m\u01F5\x03\x02\x02\x02o\u01FA\x03\x02\x02\x02" + - "q\u0205\x03\x02\x02\x02s\u0207\x03\x02\x02\x02u\u0209\x03\x02\x02\x02" + - "w\u020D\x03\x02\x02\x02y\u0211\x03\x02\x02\x02{|\x07g\x02\x02|}\x07x\x02" + - "\x02}~\x07c\x02\x02~\x7F\x07n\x02\x02\x7F\x80\x03\x02\x02\x02\x80\x81" + - "\b\x02\x02\x02\x81\x06\x03\x02\x02\x02\x82\x83\x07g\x02\x02\x83\x84\x07" + - "z\x02\x02\x84\x85\x07r\x02\x02\x85\x86\x07n\x02\x02\x86\x87\x07c\x02\x02" + - "\x87\x88\x07k\x02\x02\x88\x89\x07p\x02\x02\x89\x8A\x03\x02\x02\x02\x8A" + - "\x8B\b\x03\x02\x02\x8B\b\x03\x02\x02\x02\x8C\x8D\x07h\x02\x02\x8D\x8E" + - "\x07t\x02\x02\x8E\x8F\x07q\x02\x02\x8F\x90\x07o\x02\x02\x90\x91\x03\x02" + - "\x02\x02\x91\x92\b\x04\x03\x02\x92\n\x03\x02\x02\x02\x93\x94\x07t\x02" + - "\x02\x94\x95\x07q\x02\x02\x95\x96\x07y\x02\x02\x96\x97\x03\x02\x02\x02" + - "\x97\x98\b\x05\x02\x02\x98\f\x03\x02\x02\x02\x99\x9A\x07u\x02\x02\x9A" + - "\x9B\x07v\x02\x02\x9B\x9C\x07c\x02\x02\x9C\x9D\x07v\x02\x02\x9D\x9E\x07" + - "u\x02\x02\x9E\x9F\x03\x02\x02\x02\x9F\xA0\b\x06\x02\x02\xA0\x0E\x03\x02" + - "\x02\x02\xA1\xA2\x07y\x02\x02\xA2\xA3\x07j\x02\x02\xA3\xA4\x07g\x02\x02" + - "\xA4\xA5\x07t\x02\x02\xA5\xA6\x07g\x02\x02\xA6\xA7\x03\x02\x02\x02\xA7" + - "\xA8\b\x07\x02\x02\xA8\x10\x03\x02\x02\x02\xA9\xAA\x07u\x02\x02\xAA\xAB" + - "\x07q\x02\x02\xAB\xAC\x07t\x02\x02\xAC\xAD\x07v\x02\x02\xAD\xAE\x03\x02" + - "\x02\x02\xAE\xAF\b\b\x02\x02\xAF\x12\x03\x02\x02\x02\xB0\xB1\x07n\x02" + - "\x02\xB1\xB2\x07k\x02\x02\xB2\xB3\x07o\x02\x02\xB3\xB4\x07k\x02\x02\xB4" + - "\xB5\x07v\x02\x02\xB5\xB6\x03\x02\x02\x02\xB6\xB7\b\t\x02\x02\xB7\x14" + - "\x03\x02\x02\x02\xB8\xB9\x07r\x02\x02\xB9\xBA\x07t\x02\x02\xBA\xBB\x07" + - "q\x02\x02\xBB\xBC\x07l\x02\x02\xBC\xBD\x07g\x02\x02\xBD\xBE\x07e\x02\x02" + - "\xBE\xBF\x07v\x02\x02\xBF\xC0\x03\x02\x02\x02\xC0\xC1\b\n\x03\x02\xC1" + - "\x16\x03\x02\x02\x02\xC2\xC3\x071\x02\x02\xC3\xC4\x071\x02\x02\xC4\xC8" + - "\x03\x02\x02\x02\xC5\xC7\n\x02\x02\x02\xC6\xC5\x03\x02\x02\x02\xC7\xCA" + - "\x03\x02\x02\x02\xC8\xC6\x03\x02\x02\x02\xC8\xC9\x03\x02\x02\x02\xC9\xCC" + - "\x03\x02\x02\x02\xCA\xC8\x03\x02\x02\x02\xCB\xCD\x07\x0F\x02\x02\xCC\xCB" + - "\x03\x02\x02\x02\xCC\xCD\x03\x02\x02\x02\xCD\xCF\x03\x02\x02\x02\xCE\xD0" + - "\x07\f\x02\x02\xCF\xCE\x03\x02\x02\x02\xCF\xD0\x03\x02\x02\x02\xD0\xD1" + - "\x03\x02\x02\x02\xD1\xD2\b\v\x04\x02\xD2\x18\x03\x02\x02\x02\xD3\xD4\x07" + - "1\x02\x02\xD4\xD5\x07,\x02\x02\xD5\xDA\x03\x02\x02\x02\xD6\xD9\x05\x19" + - "\f\x02\xD7\xD9\v\x02\x02\x02\xD8\xD6\x03\x02\x02\x02\xD8\xD7\x03\x02\x02" + - "\x02\xD9\xDC\x03\x02\x02\x02\xDA\xDB\x03\x02\x02\x02\xDA\xD8\x03\x02\x02" + - "\x02\xDB\xDD\x03\x02\x02\x02\xDC\xDA\x03\x02\x02\x02\xDD\xDE\x07,\x02" + - "\x02\xDE\xDF\x071\x02\x02\xDF\xE0\x03\x02\x02\x02\xE0\xE1\b\f\x04\x02" + - "\xE1\x1A\x03\x02\x02\x02\xE2\xE4\t\x03\x02\x02\xE3\xE2\x03\x02\x02\x02" + - "\xE4\xE5\x03\x02\x02\x02\xE5\xE3\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02" + - "\xE6\xE7\x03\x02\x02\x02\xE7\xE8\b\r\x04\x02\xE8\x1C\x03\x02\x02\x02\xE9" + - "\xEA\x07~\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB\xEC\b\x0E\x05\x02\xEC\x1E" + - "\x03\x02\x02\x02\xED\xEE\t\x04\x02\x02\xEE \x03\x02\x02\x02\xEF\xF0\t" + - "\x05\x02\x02\xF0\"\x03\x02\x02\x02\xF1\xF2\x07^\x02\x02\xF2\xF3\t\x06" + - "\x02\x02\xF3$\x03\x02\x02\x02\xF4\xF5\n\x07\x02\x02\xF5&\x03\x02\x02\x02" + - "\xF6\xF8\t\b\x02\x02\xF7\xF9\t\t\x02\x02\xF8\xF7\x03\x02\x02\x02\xF8\xF9" + - "\x03\x02\x02\x02\xF9\xFB\x03\x02\x02\x02\xFA\xFC\x05\x1F\x0F\x02\xFB\xFA" + - "\x03\x02\x02\x02\xFC\xFD\x03\x02\x02\x02\xFD\xFB\x03\x02\x02\x02\xFD\xFE" + - "\x03\x02\x02\x02\xFE(\x03\x02\x02\x02\xFF\u0104\x07$\x02\x02\u0100\u0103" + - "\x05#\x11\x02\u0101\u0103\x05%\x12\x02\u0102\u0100\x03\x02\x02\x02\u0102" + - "\u0101\x03\x02\x02\x02\u0103\u0106\x03\x02\x02\x02\u0104\u0102\x03\x02" + - "\x02\x02\u0104\u0105\x03\x02\x02\x02\u0105\u0107\x03\x02\x02\x02\u0106" + - "\u0104\x03\x02\x02\x02\u0107\u011D\x07$\x02\x02\u0108\u0109\x07$\x02\x02" + - "\u0109\u010A\x07$\x02\x02\u010A\u010B\x07$\x02\x02\u010B\u010F\x03\x02" + - "\x02\x02\u010C\u010E\n\x02\x02\x02\u010D\u010C\x03\x02\x02\x02\u010E\u0111" + - "\x03\x02\x02\x02\u010F\u0110\x03\x02\x02\x02\u010F\u010D\x03\x02\x02\x02" + - "\u0110\u0112\x03\x02\x02\x02\u0111\u010F\x03\x02\x02\x02\u0112\u0113\x07" + - "$\x02\x02\u0113\u0114\x07$\x02\x02\u0114\u0115\x07$\x02\x02\u0115\u0117" + - "\x03\x02\x02\x02\u0116\u0118\x07$\x02\x02\u0117\u0116\x03\x02\x02\x02" + - "\u0117\u0118\x03\x02\x02\x02\u0118\u011A\x03\x02\x02\x02\u0119\u011B\x07" + - "$\x02\x02\u011A\u0119\x03\x02\x02\x02\u011A\u011B\x03\x02\x02\x02\u011B" + - "\u011D\x03\x02\x02\x02\u011C\xFF\x03\x02\x02\x02\u011C\u0108\x03\x02\x02" + - "\x02\u011D*\x03\x02\x02\x02\u011E\u0120\x05\x1F\x0F\x02\u011F\u011E\x03" + - "\x02\x02\x02\u0120\u0121\x03\x02\x02\x02\u0121\u011F\x03\x02\x02\x02\u0121" + - "\u0122\x03\x02\x02\x02\u0122,\x03\x02\x02\x02\u0123\u0125\x05\x1F\x0F" + - "\x02\u0124\u0123\x03\x02\x02\x02\u0125\u0126\x03\x02\x02\x02\u0126\u0124" + - "\x03\x02\x02\x02\u0126\u0127\x03\x02\x02\x02\u0127\u0128\x03\x02\x02\x02" + - "\u0128\u012C\x057\x1B\x02\u0129\u012B\x05\x1F\x0F\x02\u012A\u0129\x03" + - "\x02\x02\x02\u012B\u012E\x03\x02\x02\x02\u012C\u012A\x03\x02\x02\x02\u012C" + - "\u012D\x03\x02\x02\x02\u012D\u014E\x03\x02\x02\x02\u012E\u012C\x03\x02" + - "\x02\x02\u012F\u0131\x057\x1B\x02\u0130\u0132\x05\x1F\x0F\x02\u0131\u0130" + - "\x03\x02\x02\x02\u0132\u0133\x03\x02\x02\x02\u0133\u0131\x03\x02\x02\x02" + - "\u0133\u0134\x03\x02\x02\x02\u0134\u014E\x03\x02\x02\x02\u0135\u0137\x05" + - "\x1F\x0F\x02\u0136\u0135\x03\x02\x02\x02\u0137\u0138\x03\x02\x02\x02\u0138" + - "\u0136\x03\x02\x02\x02\u0138\u0139\x03\x02\x02\x02\u0139\u0141\x03\x02" + - "\x02\x02\u013A\u013E\x057\x1B\x02\u013B\u013D\x05\x1F\x0F\x02\u013C\u013B" + - "\x03\x02\x02\x02\u013D\u0140\x03\x02\x02\x02\u013E\u013C\x03\x02\x02\x02" + - "\u013E\u013F\x03\x02\x02\x02\u013F\u0142\x03\x02\x02\x02\u0140\u013E\x03" + - "\x02\x02\x02\u0141\u013A\x03\x02\x02\x02\u0141\u0142\x03\x02\x02\x02\u0142" + - "\u0143\x03\x02\x02\x02\u0143\u0144\x05\'\x13\x02\u0144\u014E\x03\x02\x02" + - "\x02\u0145\u0147\x057\x1B\x02\u0146\u0148\x05\x1F\x0F\x02\u0147\u0146" + - "\x03\x02\x02\x02\u0148\u0149\x03\x02\x02\x02\u0149\u0147\x03\x02\x02\x02" + - "\u0149\u014A\x03\x02\x02\x02\u014A\u014B\x03\x02\x02\x02\u014B\u014C\x05" + - "\'\x13\x02\u014C\u014E\x03\x02\x02\x02\u014D\u0124\x03\x02\x02\x02\u014D" + - "\u012F\x03\x02\x02\x02\u014D\u0136\x03\x02\x02\x02\u014D\u0145\x03\x02" + - "\x02\x02\u014E.\x03\x02\x02\x02\u014F\u0150\x07d\x02\x02\u0150\u0151\x07" + - "{\x02\x02\u01510\x03\x02\x02\x02\u0152\u0153\x07c\x02\x02\u0153\u0154" + - "\x07p\x02\x02\u0154\u0155\x07f\x02\x02\u01552\x03\x02\x02\x02\u0156\u0157" + - "\x07?\x02\x02\u01574\x03\x02\x02\x02\u0158\u0159\x07.\x02\x02\u01596\x03" + - "\x02\x02\x02\u015A\u015B\x070\x02\x02\u015B8\x03\x02\x02\x02\u015C\u015D" + - "\x07*\x02\x02\u015D:\x03\x02\x02\x02\u015E\u015F\x07]\x02\x02\u015F\u0160" + - "\x03\x02\x02\x02\u0160\u0161\b\x1D\x06\x02\u0161<\x03\x02\x02\x02\u0162" + - "\u0163\x07_\x02\x02\u0163\u0164\x03\x02\x02\x02\u0164\u0165\b\x1E\x05" + - "\x02\u0165\u0166\b\x1E\x05\x02\u0166>\x03\x02\x02\x02\u0167\u0168\x07" + - "p\x02\x02\u0168\u0169\x07q\x02\x02\u0169\u016A\x07v\x02\x02\u016A@\x03" + - "\x02\x02\x02\u016B\u016C\x07p\x02\x02\u016C\u016D\x07w\x02\x02\u016D\u016E" + - "\x07n\x02\x02\u016E\u016F\x07n\x02\x02\u016FB\x03\x02\x02\x02\u0170\u0171" + - "\x07q\x02\x02\u0171\u0172\x07t\x02\x02\u0172D\x03\x02\x02\x02\u0173\u0174" + - "\x07+\x02\x02\u0174F\x03\x02\x02\x02\u0175\u0176\x07v\x02\x02\u0176\u0177" + - "\x07t\x02\x02\u0177\u0178\x07w\x02\x02\u0178\u017F\x07g\x02\x02\u0179" + - "\u017A\x07h\x02\x02\u017A\u017B\x07c\x02\x02\u017B\u017C\x07n\x02\x02" + - "\u017C\u017D\x07u\x02\x02\u017D\u017F\x07g\x02\x02\u017E\u0175\x03\x02" + - "\x02\x02\u017E\u0179\x03\x02\x02\x02\u017FH\x03\x02\x02\x02\u0180\u0181" + - "\x07?\x02\x02\u0181\u018B\x07?\x02\x02\u0182\u0183\x07#\x02\x02\u0183" + - "\u018B\x07?\x02\x02\u0184\u018B\x07>\x02\x02\u0185\u0186\x07>\x02\x02" + - "\u0186\u018B\x07?\x02\x02\u0187\u018B\x07@\x02\x02\u0188\u0189\x07@\x02" + - "\x02\u0189\u018B\x07?\x02\x02\u018A\u0180\x03\x02\x02\x02\u018A\u0182" + - "\x03\x02\x02\x02\u018A\u0184\x03\x02\x02\x02\u018A\u0185\x03\x02\x02\x02" + - "\u018A\u0187\x03\x02\x02\x02\u018A\u0188\x03\x02\x02\x02\u018BJ\x03\x02" + - "\x02\x02\u018C\u018D\x07-\x02\x02\u018DL\x03\x02\x02\x02\u018E\u018F\x07" + - "/\x02\x02\u018FN\x03\x02\x02\x02\u0190\u0191\x07,\x02\x02\u0191P\x03\x02" + - "\x02\x02\u0192\u0193\x071\x02\x02\u0193R\x03\x02\x02\x02\u0194\u0195\x07" + - "\'\x02\x02\u0195T\x03\x02\x02\x02\u0196\u0197\x07c\x02\x02\u0197\u0198" + - "\x07u\x02\x02\u0198\u019E\x07e\x02\x02\u0199\u019A\x07f\x02\x02\u019A" + - "\u019B\x07g\x02\x02\u019B\u019C\x07u\x02\x02\u019C\u019E\x07e\x02\x02" + - "\u019D\u0196\x03\x02\x02\x02\u019D\u0199\x03\x02\x02\x02\u019EV\x03\x02" + - "\x02\x02\u019F\u01A0\x07p\x02\x02\u01A0\u01A1\x07w\x02\x02\u01A1\u01A2" + - "\x07n\x02\x02\u01A2\u01A3\x07n\x02\x02\u01A3\u01A4\x07u\x02\x02\u01A4" + - "X\x03\x02\x02\x02\u01A5\u01A6\x07h\x02\x02\u01A6\u01A7\x07k\x02\x02\u01A7" + - "\u01A8\x07t\x02\x02\u01A8\u01A9\x07u\x02\x02\u01A9\u01AF\x07v\x02\x02" + - "\u01AA\u01AB\x07n\x02\x02\u01AB\u01AC\x07c\x02\x02\u01AC\u01AD\x07u\x02" + - "\x02\u01AD\u01AF\x07v\x02\x02\u01AE\u01A5\x03\x02\x02\x02\u01AE\u01AA" + - "\x03\x02\x02\x02\u01AFZ\x03\x02\x02\x02\u01B0\u01B1\x07t\x02\x02\u01B1" + - "\u01B2\x07q\x02\x02\u01B2\u01B3\x07w\x02\x02\u01B3\u01B4\x07p\x02\x02" + - "\u01B4\u01C2\x07f\x02\x02\u01B5\u01B6\x07c\x02\x02\u01B6\u01B7\x07x\x02" + - "\x02\u01B7\u01C2\x07i\x02\x02\u01B8\u01B9\x07o\x02\x02\u01B9\u01BA\x07" + - "k\x02\x02\u01BA\u01C2\x07p\x02\x02\u01BB\u01BC\x07o\x02\x02\u01BC\u01BD" + - "\x07c\x02\x02\u01BD\u01C2\x07z\x02\x02\u01BE\u01BF\x07u\x02\x02\u01BF" + - "\u01C0\x07w\x02\x02\u01C0\u01C2\x07o\x02\x02\u01C1\u01B0\x03\x02\x02\x02" + - "\u01C1\u01B5\x03\x02\x02\x02\u01C1\u01B8\x03\x02\x02\x02\u01C1\u01BB\x03" + - "\x02\x02\x02\u01C1\u01BE\x03\x02\x02\x02\u01C2\\\x03\x02\x02\x02\u01C3" + - "\u01C6\x05!\x10\x02\u01C4\u01C6\x07a\x02\x02\u01C5\u01C3\x03\x02\x02\x02" + - "\u01C5\u01C4\x03\x02\x02\x02\u01C6\u01CC\x03\x02\x02\x02\u01C7\u01CB\x05" + - "!\x10\x02\u01C8\u01CB\x05\x1F\x0F\x02\u01C9\u01CB\x07a\x02\x02\u01CA\u01C7" + - "\x03\x02\x02\x02\u01CA\u01C8\x03\x02\x02\x02\u01CA\u01C9\x03\x02\x02\x02" + - "\u01CB\u01CE\x03\x02\x02\x02\u01CC\u01CA\x03\x02\x02\x02\u01CC\u01CD\x03" + - "\x02\x02\x02\u01CD^\x03\x02\x02\x02\u01CE\u01CC\x03\x02\x02\x02\u01CF" + - "\u01D5\x07b\x02\x02\u01D0\u01D4\n\n\x02\x02\u01D1\u01D2\x07b\x02\x02\u01D2" + - "\u01D4\x07b\x02\x02\u01D3\u01D0\x03\x02\x02\x02\u01D3\u01D1\x03\x02\x02" + - "\x02\u01D4\u01D7\x03\x02\x02\x02\u01D5\u01D3\x03\x02\x02\x02\u01D5\u01D6" + - "\x03\x02\x02\x02\u01D6\u01D8\x03\x02\x02\x02\u01D7\u01D5\x03\x02\x02\x02" + - "\u01D8\u01D9\x07b\x02\x02\u01D9`\x03\x02\x02\x02\u01DA\u01DB\x05\x17\v" + - "\x02\u01DB\u01DC\x03\x02\x02\x02\u01DC\u01DD\b0\x04\x02\u01DDb\x03\x02" + - "\x02\x02\u01DE\u01DF\x05\x19\f\x02\u01DF\u01E0\x03\x02\x02\x02\u01E0\u01E1" + - "\b1\x04\x02\u01E1d\x03\x02\x02\x02\u01E2\u01E3\x05\x1B\r\x02\u01E3\u01E4" + - "\x03\x02\x02\x02\u01E4\u01E5\b2\x04\x02\u01E5f\x03\x02\x02\x02\u01E6\u01E7" + - "\x07~\x02\x02\u01E7\u01E8\x03\x02\x02\x02\u01E8\u01E9\b3\x07\x02\u01E9" + - "\u01EA\b3\x05\x02\u01EAh\x03\x02\x02\x02\u01EB\u01EC\x07_\x02\x02\u01EC" + - "\u01ED\x03\x02\x02\x02\u01ED\u01EE\b4\x05\x02\u01EE\u01EF\b4\x05\x02\u01EF" + - "\u01F0\b4\b\x02\u01F0j\x03\x02\x02\x02\u01F1\u01F2\x07.\x02\x02\u01F2" + - "\u01F3\x03\x02\x02\x02\u01F3\u01F4\b5\t\x02\u01F4l\x03\x02\x02\x02\u01F5" + - "\u01F6\x07?\x02\x02\u01F6\u01F7\x03\x02\x02\x02\u01F7\u01F8\b6\n\x02\u01F8" + - "n\x03\x02\x02\x02\u01F9\u01FB\x05q8\x02\u01FA\u01F9\x03\x02\x02\x02\u01FB" + - "\u01FC\x03\x02\x02\x02\u01FC\u01FA\x03\x02\x02\x02\u01FC\u01FD\x03\x02" + - "\x02\x02\u01FDp\x03\x02\x02\x02\u01FE\u0200\n\v\x02\x02\u01FF\u01FE\x03" + - "\x02\x02\x02\u0200\u0201\x03\x02\x02\x02\u0201\u01FF\x03\x02\x02\x02\u0201" + - "\u0202\x03\x02\x02\x02\u0202\u0206\x03\x02\x02\x02\u0203\u0204\x071\x02" + - "\x02\u0204\u0206\n\f\x02\x02\u0205\u01FF\x03\x02\x02\x02\u0205\u0203\x03" + - "\x02\x02\x02\u0206r\x03\x02\x02\x02\u0207\u0208\x05_/\x02\u0208t\x03\x02" + - "\x02\x02\u0209\u020A\x05\x17\v\x02\u020A\u020B\x03\x02\x02\x02\u020B\u020C" + - "\b:\x04\x02\u020Cv\x03\x02\x02\x02\u020D\u020E\x05\x19\f\x02\u020E\u020F" + - "\x03\x02\x02\x02\u020F\u0210\b;\x04\x02\u0210x\x03\x02\x02\x02\u0211\u0212" + - "\x05\x1B\r\x02\u0212\u0213\x03\x02\x02\x02\u0213\u0214\b<\x04\x02\u0214" + - "z\x03\x02\x02\x02)\x02\x03\x04\xC8\xCC\xCF\xD8\xDA\xE5\xF8\xFD\u0102\u0104" + - "\u010F\u0117\u011A\u011C\u0121\u0126\u012C\u0133\u0138\u013E\u0141\u0149" + - "\u014D\u017E\u018A\u019D\u01AE\u01C1\u01C5\u01CA\u01CC\u01D3\u01D5\u01FC" + - "\u0201\u0205\v\x07\x03\x02\x07\x04\x02\x02\x03\x02\x06\x02\x02\x07\x02" + - "\x02\t\x0F\x02\t\x1A\x02\t\x16\x02\t\x15\x02"; + private static readonly _serializedATNSegments: number = 3; + private static readonly _serializedATNSegment0: string = + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x02S\u0574\b\x01" + + "\b\x01\b\x01\b\x01\b\x01\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04" + + "\x05\t\x05\x04\x06\t\x06\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04" + + "\v\t\v\x04\f\t\f\x04\r\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04" + + "\x11\t\x11\x04\x12\t\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04" + + "\x16\t\x16\x04\x17\t\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04" + + "\x1B\t\x1B\x04\x1C\t\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04" + + " \t \x04!\t!\x04\"\t\"\x04#\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(" + + "\t(\x04)\t)\x04*\t*\x04+\t+\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x040\t0\x04" + + "1\t1\x042\t2\x043\t3\x044\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04" + + ":\t:\x04;\t;\x04<\t<\x04=\t=\x04>\t>\x04?\t?\x04@\t@\x04A\tA\x04B\tB\x04" + + "C\tC\x04D\tD\x04E\tE\x04F\tF\x04G\tG\x04H\tH\x04I\tI\x04J\tJ\x04K\tK\x04" + + "L\tL\x04M\tM\x04N\tN\x04O\tO\x04P\tP\x04Q\tQ\x04R\tR\x04S\tS\x04T\tT\x04" + + "U\tU\x04V\tV\x04W\tW\x04X\tX\x04Y\tY\x04Z\tZ\x04[\t[\x04\\\t\\\x04]\t" + + "]\x04^\t^\x04_\t_\x04`\t`\x04a\ta\x04b\tb\x04c\tc\x04d\td\x04e\te\x04" + + "f\tf\x04g\tg\x04h\th\x04i\ti\x04j\tj\x04k\tk\x04l\tl\x04m\tm\x04n\tn\x04" + + "o\to\x04p\tp\x04q\tq\x04r\tr\x04s\ts\x04t\tt\x04u\tu\x04v\tv\x04w\tw\x04" + + "x\tx\x04y\ty\x04z\tz\x04{\t{\x04|\t|\x04}\t}\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03" + + "\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x05\x03\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03" + + "\x06\x03\x06\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\b\x03" + + "\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03" + + "\t\x03\t\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03" + + "\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03" + + "\f\x03\f\x03\f\x03\f\x03\f\x03\f\x03\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + + "\r\x03\r\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03" + + "\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03" + + "\x0F\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03" + + "\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x12\x03" + + "\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x13\x03\x13\x03\x13\x03" + + "\x13\x07\x13\u018F\n\x13\f\x13\x0E\x13\u0192\v\x13\x03\x13\x05\x13\u0195" + + "\n\x13\x03\x13\x05\x13\u0198\n\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03" + + "\x14\x03\x14\x03\x14\x07\x14\u01A1\n\x14\f\x14\x0E\x14\u01A4\v\x14\x03" + + "\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03\x15\x06\x15\u01AC\n\x15\r\x15" + + "\x0E\x15\u01AD\x03\x15\x03\x15\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16" + + "\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x18\x03\x18\x03\x18\x03\x18" + + "\x03\x19\x03\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B" + + "\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1D\x03\x1D\x03\x1E\x03\x1E" + + "\x03\x1E\x03\x1F\x03\x1F\x03 \x03 \x05 \u01D7\n \x03 \x06 \u01DA\n \r" + + " \x0E \u01DB\x03!\x03!\x03!\x07!\u01E1\n!\f!\x0E!\u01E4\v!\x03!\x03!\x03" + + "!\x03!\x03!\x03!\x07!\u01EC\n!\f!\x0E!\u01EF\v!\x03!\x03!\x03!\x03!\x03" + + "!\x05!\u01F6\n!\x03!\x05!\u01F9\n!\x05!\u01FB\n!\x03\"\x06\"\u01FE\n\"" + + "\r\"\x0E\"\u01FF\x03#\x06#\u0203\n#\r#\x0E#\u0204\x03#\x03#\x07#\u0209" + + "\n#\f#\x0E#\u020C\v#\x03#\x03#\x06#\u0210\n#\r#\x0E#\u0211\x03#\x06#\u0215" + + "\n#\r#\x0E#\u0216\x03#\x03#\x07#\u021B\n#\f#\x0E#\u021E\v#\x05#\u0220" + + "\n#\x03#\x03#\x03#\x03#\x06#\u0226\n#\r#\x0E#\u0227\x03#\x03#\x05#\u022C" + + "\n#\x03$\x03$\x03$\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + + "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + + "%\x03%\x03%\x03%\x05%\u024D\n%\x03&\x03&\x03&\x03&\x03\'\x03\'\x03(\x03" + + "(\x03)\x03)\x03*\x03*\x03+\x03+\x03+\x03+\x03+\x03,\x03,\x03,\x03,\x03" + + ",\x03-\x03-\x03-\x03-\x03.\x03.\x03.\x03.\x03.\x03/\x03/\x03/\x03/\x03" + + "/\x03/\x030\x030\x030\x031\x031\x031\x032\x032\x032\x033\x033\x033\x03" + + "3\x033\x034\x034\x034\x035\x035\x036\x036\x037\x037\x037\x037\x037\x03" + + "8\x038\x038\x038\x038\x038\x038\x038\x038\x038\x039\x039\x039\x039\x03" + + "9\x039\x039\x039\x039\x059\u02A1\n9\x03:\x03:\x03:\x03:\x03:\x03:\x03" + + ":\x03:\x03:\x03:\x05:\u02AD\n:\x03;\x03;\x03<\x03<\x03=\x03=\x03>\x03" + + ">\x03?\x03?\x03@\x03@\x03@\x03A\x03A\x03A\x03A\x03A\x03A\x03A\x05A\u02C3" + + "\nA\x03B\x03B\x03B\x03B\x03B\x03B\x03C\x03C\x03C\x03C\x03C\x03C\x03C\x03" + + "C\x03C\x05C\u02D4\nC\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + + "D\x03D\x03D\x05D\u0440\nD\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + + "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + + "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + + "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + + "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + + "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + + "E\x03E\x03E\x05E\u0493\nE\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03" + + "F\x03F\x03F\x03G\x03G\x03G\x03G\x03G\x07G\u04A5\nG\fG\x0EG\u04A8\vG\x03" + + "G\x03G\x03G\x03G\x03G\x06G\u04AF\nG\rG\x0EG\u04B0\x05G\u04B3\nG\x03H\x03" + + "H\x03H\x03H\x07H\u04B9\nH\fH\x0EH\u04BC\vH\x03H\x03H\x03I\x03I\x03I\x03" + + "I\x03J\x03J\x03J\x03J\x03K\x03K\x03K\x03K\x03L\x03L\x03L\x03L\x03L\x03" + + "M\x03M\x03M\x03M\x03M\x03M\x03N\x03N\x03N\x03N\x03N\x03N\x03O\x03O\x03" + + "O\x03O\x03P\x03P\x03P\x03P\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03" + + "Q\x03R\x06R\u04EF\nR\rR\x0ER\u04F0\x03S\x06S\u04F4\nS\rS\x0ES\u04F5\x03" + + "S\x03S\x05S\u04FA\nS\x03T\x03T\x03U\x03U\x03U\x03U\x03V\x03V\x03V\x03" + + "V\x03W\x03W\x03W\x03W\x03X\x03X\x03X\x03Y\x03Y\x03Y\x03Y\x03Y\x03Z\x03" + + "Z\x03Z\x03Z\x03Z\x03[\x03[\x03[\x03[\x03[\x03[\x03\\\x03\\\x03\\\x03\\" + + "\x03]\x03]\x03]\x03]\x03^\x06^\u0526\n^\r^\x0E^\u0527\x03_\x06_\u052B" + + "\n_\r_\x0E_\u052C\x03_\x03_\x05_\u0531\n_\x03`\x03`\x03a\x03a\x03a\x03" + + "a\x03b\x03b\x03b\x03b\x03c\x03c\x03c\x03c\x03d\x03d\x03e\x03e\x03f\x03" + + "f\x03g\x03g\x03h\x03h\x03i\x03i\x03j\x03j\x03k\x03k\x03l\x03l\x03m\x03" + + "m\x03n\x03n\x03o\x03o\x03p\x03p\x03q\x03q\x03r\x03r\x03s\x03s\x03t\x03" + + "t\x03u\x03u\x03v\x03v\x03w\x03w\x03x\x03x\x03y\x03y\x03z\x03z\x03{\x03" + + "{\x03|\x03|\x03}\x03}\x04\u01A2\u01ED\x02\x02~\x07\x02\x03\t\x02\x04\v" + + "\x02\x05\r\x02\x06\x0F\x02\x07\x11\x02\b\x13\x02\t\x15\x02\n\x17\x02\v" + + "\x19\x02\f\x1B\x02\r\x1D\x02\x0E\x1F\x02\x0F!\x02\x10#\x02\x11%\x02\x12" + + "\'\x02\x13)\x02\x14+\x02\x15-\x02\x16/\x02\x021\x02S3\x02\x175\x02\x18" + + "7\x02\x199\x02\x1A;\x02\x02=\x02\x02?\x02\x02A\x02\x02C\x02\x02E\x02\x1B" + + "G\x02\x1CI\x02\x1DK\x02\x1EM\x02\x1FO\x02 Q\x02!S\x02\"U\x02#W\x02$Y\x02" + + "%[\x02&]\x02\'_\x02(a\x02)c\x02*e\x02+g\x02,i\x02-k\x02.m\x02/o\x020q" + + "\x021s\x022u\x023w\x024y\x025{\x026}\x027\x7F\x028\x81\x029\x83\x02:\x85" + + "\x02;\x87\x02<\x89\x02=\x8B\x02>\x8D\x02?\x8F\x02@\x91\x02A\x93\x02B\x95" + + "\x02C\x97\x02D\x99\x02E\x9B\x02\x02\x9D\x02\x02\x9F\x02\x02\xA1\x02\x02" + + "\xA3\x02\x02\xA5\x02F\xA7\x02G\xA9\x02\x02\xAB\x02H\xAD\x02I\xAF\x02J" + + "\xB1\x02K\xB3\x02L\xB5\x02M\xB7\x02\x02\xB9\x02\x02\xBB\x02\x02\xBD\x02" + + "\x02\xBF\x02N\xC1\x02\x02\xC3\x02O\xC5\x02P\xC7\x02Q\xC9\x02R\xCB\x02" + + "\x02\xCD\x02\x02\xCF\x02\x02\xD1\x02\x02\xD3\x02\x02\xD5\x02\x02\xD7\x02" + + "\x02\xD9\x02\x02\xDB\x02\x02\xDD\x02\x02\xDF\x02\x02\xE1\x02\x02\xE3\x02" + + "\x02\xE5\x02\x02\xE7\x02\x02\xE9\x02\x02\xEB\x02\x02\xED\x02\x02\xEF\x02" + + "\x02\xF1\x02\x02\xF3\x02\x02\xF5\x02\x02\xF7\x02\x02\xF9\x02\x02\xFB\x02" + + "\x02\xFD\x02\x02\x07\x02\x03\x04\x05\x06\'\x04\x02\f\f\x0F\x0F\x05\x02" + + "\v\f\x0F\x0F\"\"\x03\x022;\x04\x02C\\c|\x07\x02$$^^ppttvv\x06\x02\f\f" + + "\x0F\x0F$$^^\x04\x02GGgg\x04\x02--//\x04\x02BBaa\x03\x02bb\f\x02\v\f\x0F" + + "\x0F\"\"..11??]]__bb~~\x04\x02,,11\x04\x02CCcc\x04\x02DDdd\x04\x02EEe" + + "e\x04\x02FFff\x04\x02HHhh\x04\x02IIii\x04\x02JJjj\x04\x02KKkk\x04\x02" + + "LLll\x04\x02MMmm\x04\x02NNnn\x04\x02OOoo\x04\x02PPpp\x04\x02QQqq\x04\x02" + + "RRrr\x04\x02SSss\x04\x02TTtt\x04\x02UUuu\x04\x02VVvv\x04\x02WWww\x04\x02" + + "XXxx\x04\x02YYyy\x04\x02ZZzz\x04\x02[[{{\x04\x02\\\\||\x02\u05B8\x02\x07" + + "\x03\x02\x02\x02\x02\t\x03\x02\x02\x02\x02\v\x03\x02\x02\x02\x02\r\x03" + + "\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02\x11\x03\x02\x02\x02\x02\x13\x03" + + "\x02\x02\x02\x02\x15\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02\x19\x03" + + "\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02\x1F\x03" + + "\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03\x02\x02" + + "\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02\x02\x02" + + "-\x03\x02\x02\x02\x03/\x03\x02\x02\x02\x031\x03\x02\x02\x02\x033\x03\x02" + + "\x02\x02\x035\x03\x02\x02\x02\x037\x03\x02\x02\x02\x049\x03\x02\x02\x02" + + "\x04E\x03\x02\x02\x02\x04G\x03\x02\x02\x02\x04I\x03\x02\x02\x02\x04K\x03" + + "\x02\x02\x02\x04M\x03\x02\x02\x02\x04O\x03\x02\x02\x02\x04Q\x03\x02\x02" + + "\x02\x04S\x03\x02\x02\x02\x04U\x03\x02\x02\x02\x04W\x03\x02\x02\x02\x04" + + "Y\x03\x02\x02\x02\x04[\x03\x02\x02\x02\x04]\x03\x02\x02\x02\x04_\x03\x02" + + "\x02\x02\x04a\x03\x02\x02\x02\x04c\x03\x02\x02\x02\x04e\x03\x02\x02\x02" + + "\x04g\x03\x02\x02\x02\x04i\x03\x02\x02\x02\x04k\x03\x02\x02\x02\x04m\x03" + + "\x02\x02\x02\x04o\x03\x02\x02\x02\x04q\x03\x02\x02\x02\x04s\x03\x02\x02" + + "\x02\x04u\x03\x02\x02\x02\x04w\x03\x02\x02\x02\x04y\x03\x02\x02\x02\x04" + + "{\x03\x02\x02\x02\x04}\x03\x02\x02\x02\x04\x7F\x03\x02\x02\x02\x04\x81" + + "\x03\x02\x02\x02\x04\x83\x03\x02\x02\x02\x04\x85\x03\x02\x02\x02\x04\x87" + + "\x03\x02\x02\x02\x04\x89\x03\x02\x02\x02\x04\x8B\x03\x02\x02\x02\x04\x8D" + + "\x03\x02\x02\x02\x04\x8F\x03\x02\x02\x02\x04\x91\x03\x02\x02\x02\x04\x93" + + "\x03\x02\x02\x02\x04\x95\x03\x02\x02\x02\x04\x97\x03\x02\x02\x02\x04\x99" + + "\x03\x02\x02\x02\x05\x9B\x03\x02\x02\x02\x05\x9D\x03\x02\x02\x02\x05\x9F" + + "\x03\x02\x02\x02\x05\xA1\x03\x02\x02\x02\x05\xA3\x03\x02\x02\x02\x05\xA5" + + "\x03\x02\x02\x02\x05\xA7\x03\x02\x02\x02\x05\xAB\x03\x02\x02\x02\x05\xAD" + + "\x03\x02\x02\x02\x05\xAF\x03\x02\x02\x02\x05\xB1\x03\x02\x02\x02\x06\xB3" + + "\x03\x02\x02\x02\x06\xB5\x03\x02\x02\x02\x06\xB7\x03\x02\x02\x02\x06\xB9" + + "\x03\x02\x02\x02\x06\xBB\x03\x02\x02\x02\x06\xBD\x03\x02\x02\x02\x06\xBF" + + "\x03\x02\x02\x02\x06\xC3\x03\x02\x02\x02\x06\xC5\x03\x02\x02\x02\x06\xC7" + + "\x03\x02\x02\x02\x06\xC9\x03\x02\x02\x02\x07\xFF\x03\x02\x02\x02\t\u0109" + + "\x03\x02\x02\x02\v\u0110\x03\x02\x02\x02\r\u0117\x03\x02\x02\x02\x0F\u0121" + + "\x03\x02\x02\x02\x11\u0128\x03\x02\x02\x02\x13\u012E\x03\x02\x02\x02\x15" + + "\u0136\x03\x02\x02\x02\x17\u013E\x03\x02\x02\x02\x19\u0145\x03\x02\x02" + + "\x02\x1B\u0151\x03\x02\x02\x02\x1D\u0159\x03\x02\x02\x02\x1F\u0163\x03" + + "\x02\x02\x02!\u016A\x03\x02\x02\x02#\u0173\x03\x02\x02\x02%\u017A\x03" + + "\x02\x02\x02\'\u0183\x03\x02\x02\x02)\u018A\x03\x02\x02\x02+\u019B\x03" + + "\x02\x02\x02-\u01AB\x03\x02\x02\x02/\u01B1\x03\x02\x02\x021\u01B6\x03" + + "\x02\x02\x023\u01BB\x03\x02\x02\x025\u01BF\x03\x02\x02\x027\u01C3\x03" + + "\x02\x02\x029\u01C7\x03\x02\x02\x02;\u01CB\x03\x02\x02\x02=\u01CD\x03" + + "\x02\x02\x02?\u01CF\x03\x02\x02\x02A\u01D2\x03\x02\x02\x02C\u01D4\x03" + + "\x02\x02\x02E\u01FA\x03\x02\x02\x02G\u01FD\x03\x02\x02\x02I\u022B\x03" + + "\x02\x02\x02K\u022D\x03\x02\x02\x02M\u024C\x03\x02\x02\x02O\u024E\x03" + + "\x02\x02\x02Q\u0252\x03\x02\x02\x02S\u0254\x03\x02\x02\x02U\u0256\x03" + + "\x02\x02\x02W\u0258\x03\x02\x02\x02Y\u025A\x03\x02\x02\x02[\u025F\x03" + + "\x02\x02\x02]\u0264\x03\x02\x02\x02_\u0268\x03\x02\x02\x02a\u026D\x03" + + "\x02\x02\x02c\u0273\x03\x02\x02\x02e\u0276\x03\x02\x02\x02g\u0279\x03" + + "\x02\x02\x02i\u027C\x03\x02\x02\x02k\u0281\x03\x02\x02\x02m\u0284\x03" + + "\x02\x02\x02o\u0286\x03\x02\x02\x02q\u0288\x03\x02\x02\x02s\u028D\x03" + + "\x02\x02\x02u\u02A0\x03\x02\x02\x02w\u02AC\x03\x02\x02\x02y\u02AE\x03" + + "\x02\x02\x02{\u02B0\x03\x02\x02\x02}\u02B2\x03\x02\x02\x02\x7F\u02B4\x03" + + "\x02\x02\x02\x81\u02B6\x03\x02\x02\x02\x83\u02B8\x03\x02\x02\x02\x85\u02C2" + + "\x03\x02\x02\x02\x87\u02C4\x03\x02\x02\x02\x89\u02D3\x03\x02\x02\x02\x8B" + + "\u043F\x03\x02\x02\x02\x8D\u0492\x03\x02\x02\x02\x8F\u0494\x03\x02\x02" + + "\x02\x91\u04B2\x03\x02\x02\x02\x93\u04B4\x03\x02\x02\x02\x95\u04BF\x03" + + "\x02\x02\x02\x97\u04C3\x03\x02\x02\x02\x99\u04C7\x03\x02\x02\x02\x9B\u04CB" + + "\x03\x02\x02\x02\x9D\u04D0\x03\x02\x02\x02\x9F\u04D6\x03\x02\x02\x02\xA1" + + "\u04DC\x03\x02\x02\x02\xA3\u04E0\x03\x02\x02\x02\xA5\u04E4\x03\x02\x02" + + "\x02\xA7\u04EE\x03\x02\x02\x02\xA9\u04F9\x03\x02\x02\x02\xAB\u04FB\x03" + + "\x02\x02\x02\xAD\u04FD\x03\x02\x02\x02\xAF\u0501\x03\x02\x02\x02\xB1\u0505" + + "\x03\x02\x02\x02\xB3\u0509\x03\x02\x02\x02\xB5\u050C\x03\x02\x02\x02\xB7" + + "\u0511\x03\x02\x02\x02\xB9\u0516\x03\x02\x02\x02\xBB\u051C\x03\x02\x02" + + "\x02\xBD\u0520\x03\x02\x02\x02\xBF\u0525\x03\x02\x02\x02\xC1\u0530\x03" + + "\x02\x02\x02\xC3\u0532\x03\x02\x02\x02\xC5\u0534\x03\x02\x02\x02\xC7\u0538" + + "\x03\x02\x02\x02\xC9\u053C\x03\x02\x02\x02\xCB\u0540\x03\x02\x02\x02\xCD" + + "\u0542\x03\x02\x02\x02\xCF\u0544\x03\x02\x02\x02\xD1\u0546\x03\x02\x02" + + "\x02\xD3\u0548\x03\x02\x02\x02\xD5\u054A\x03\x02\x02\x02\xD7\u054C\x03" + + "\x02\x02\x02\xD9\u054E\x03\x02\x02\x02\xDB\u0550\x03\x02\x02\x02\xDD\u0552" + + "\x03\x02\x02\x02\xDF\u0554\x03\x02\x02\x02\xE1\u0556\x03\x02\x02\x02\xE3" + + "\u0558\x03\x02\x02\x02\xE5\u055A\x03\x02\x02\x02\xE7\u055C\x03\x02\x02" + + "\x02\xE9\u055E\x03\x02\x02\x02\xEB\u0560\x03\x02\x02\x02\xED\u0562\x03" + + "\x02\x02\x02\xEF\u0564\x03\x02\x02\x02\xF1\u0566\x03\x02\x02\x02\xF3\u0568" + + "\x03\x02\x02\x02\xF5\u056A\x03\x02\x02\x02\xF7\u056C\x03\x02\x02\x02\xF9" + + "\u056E\x03\x02\x02\x02\xFB\u0570\x03\x02\x02\x02\xFD\u0572\x03\x02\x02" + + "\x02\xFF\u0100\x05\xD1g\x02\u0100\u0101\x05\xDBl\x02\u0101\u0102\x05\xEF" + + "v\x02\u0102\u0103\x05\xEFv\x02\u0103\u0104\x05\xD3h\x02\u0104\u0105\x05" + + "\xCFf\x02\u0105\u0106\x05\xF1w\x02\u0106\u0107\x03\x02\x02\x02\u0107\u0108" + + "\b\x02\x02\x02\u0108\b\x03\x02\x02\x02\u0109\u010A\x05\xD7j\x02\u010A" + + "\u010B\x05\xEDu\x02\u010B\u010C\x05\xE7r\x02\u010C\u010D\x05\xDFn\x02" + + "\u010D\u010E\x03\x02\x02\x02\u010E\u010F\b\x03\x02\x02\u010F\n\x03\x02" + + "\x02\x02\u0110\u0111\x05\xD3h\x02\u0111\u0112\x05\xF5y\x02\u0112\u0113" + + "\x05\xCBd\x02\u0113\u0114\x05\xE1o\x02\u0114\u0115\x03\x02\x02\x02\u0115" + + "\u0116\b\x04\x02\x02\u0116\f\x03\x02\x02\x02\u0117\u0118\x05\xD3h\x02" + + "\u0118\u0119\x05\xF9{\x02\u0119\u011A\x05\xE9s\x02\u011A\u011B\x05\xE1" + + "o\x02\u011B\u011C\x05\xCBd\x02\u011C\u011D\x05\xDBl\x02\u011D\u011E\x05" + + "\xE5q\x02\u011E\u011F\x03\x02\x02\x02\u011F\u0120\b\x05\x03\x02\u0120" + + "\x0E\x03\x02\x02\x02\u0121\u0122\x05\xD5i\x02\u0122\u0123\x05\xEDu\x02" + + "\u0123\u0124\x05"; + private static readonly _serializedATNSegment1: string = + "\xE7r\x02\u0124\u0125\x05\xE3p\x02\u0125\u0126\x03\x02\x02\x02\u0126\u0127" + + "\b\x06\x04\x02\u0127\x10\x03\x02\x02\x02\u0128\u0129\x05\xEDu\x02\u0129" + + "\u012A\x05\xE7r\x02\u012A\u012B\x05\xF7z\x02\u012B\u012C\x03\x02\x02\x02" + + "\u012C\u012D\b\x07\x02\x02\u012D\x12\x03\x02\x02\x02\u012E\u012F\x05\xEF" + + "v\x02\u012F\u0130\x05\xF1w\x02\u0130\u0131\x05\xCBd\x02\u0131\u0132\x05" + + "\xF1w\x02\u0132\u0133\x05\xEFv\x02\u0133\u0134\x03\x02\x02\x02\u0134\u0135" + + "\b\b\x02\x02\u0135\x14\x03\x02\x02\x02\u0136\u0137\x05\xF7z\x02\u0137" + + "\u0138\x05\xD9k\x02\u0138\u0139\x05\xD3h\x02\u0139\u013A\x05\xEDu\x02" + + "\u013A\u013B\x05\xD3h\x02\u013B\u013C\x03\x02\x02\x02\u013C\u013D\b\t" + + "\x02\x02\u013D\x16\x03\x02\x02\x02\u013E\u013F\x05\xEFv\x02\u013F\u0140" + + "\x05\xE7r\x02\u0140\u0141\x05\xEDu\x02\u0141\u0142\x05\xF1w\x02\u0142" + + "\u0143\x03\x02\x02\x02\u0143\u0144\b\n\x02\x02\u0144\x18\x03\x02\x02\x02" + + "\u0145\u0146\x05\xE3p\x02\u0146\u0147\x05\xF5y\x02\u0147\u0148\x05o6\x02" + + "\u0148\u0149\x05\xD3h\x02\u0149\u014A\x05\xF9{\x02\u014A\u014B\x05\xE9" + + "s\x02\u014B\u014C\x05\xCBd\x02\u014C\u014D\x05\xE5q\x02\u014D\u014E\x05" + + "\xD1g\x02\u014E\u014F\x03\x02\x02\x02\u014F\u0150\b\v\x02\x02\u0150\x1A" + + "\x03\x02\x02\x02\u0151\u0152\x05\xE1o\x02\u0152\u0153\x05\xDBl\x02\u0153" + + "\u0154\x05\xE3p\x02\u0154\u0155\x05\xDBl\x02\u0155\u0156\x05\xF1w\x02" + + "\u0156\u0157\x03\x02\x02\x02\u0157\u0158\b\f\x02\x02\u0158\x1C\x03\x02" + + "\x02\x02\u0159\u015A\x05\xE9s\x02\u015A\u015B\x05\xEDu\x02\u015B\u015C" + + "\x05\xE7r\x02\u015C\u015D\x05\xDDm\x02\u015D\u015E\x05\xD3h\x02\u015E" + + "\u015F\x05\xCFf\x02\u015F\u0160\x05\xF1w\x02\u0160\u0161\x03\x02\x02\x02" + + "\u0161\u0162\b\r\x02\x02\u0162\x1E\x03\x02\x02\x02\u0163\u0164\x05\xD1" + + "g\x02\u0164\u0165\x05\xEDu\x02\u0165\u0166\x05\xE7r\x02\u0166\u0167\x05" + + "\xE9s\x02\u0167\u0168\x03\x02\x02\x02\u0168\u0169\b\x0E\x02\x02\u0169" + + " \x03\x02\x02\x02\u016A\u016B\x05\xEDu\x02\u016B\u016C\x05\xD3h\x02\u016C" + + "\u016D\x05\xE5q\x02\u016D\u016E\x05\xCBd\x02\u016E\u016F\x05\xE3p\x02" + + "\u016F\u0170\x05\xD3h\x02\u0170\u0171\x03\x02\x02\x02\u0171\u0172\b\x0F" + + "\x02\x02\u0172\"\x03\x02\x02\x02\u0173\u0174\x05\xEFv\x02\u0174\u0175" + + "\x05\xD9k\x02\u0175\u0176\x05\xE7r\x02\u0176\u0177\x05\xF7z\x02\u0177" + + "\u0178\x03\x02\x02\x02\u0178\u0179\b\x10\x02\x02\u0179$\x03\x02\x02\x02" + + "\u017A\u017B\x05\xD3h\x02\u017B\u017C\x05\xE5q\x02\u017C\u017D\x05\xED" + + "u\x02\u017D\u017E\x05\xDBl\x02\u017E\u017F\x05\xCFf\x02\u017F\u0180\x05" + + "\xD9k\x02\u0180\u0181\x03\x02\x02\x02\u0181\u0182\b\x11\x05\x02\u0182" + + "&\x03\x02\x02\x02\u0183\u0184\x05\xDFn\x02\u0184\u0185\x05\xD3h\x02\u0185" + + "\u0186\x05\xD3h\x02\u0186\u0187\x05\xE9s\x02\u0187\u0188\x03\x02\x02\x02" + + "\u0188\u0189\b\x12\x02\x02\u0189(\x03\x02\x02\x02\u018A\u018B\x071\x02" + + "\x02\u018B\u018C\x071\x02\x02\u018C\u0190\x03\x02\x02\x02\u018D\u018F" + + "\n\x02\x02\x02\u018E\u018D\x03\x02\x02\x02\u018F\u0192\x03\x02\x02\x02" + + "\u0190\u018E\x03\x02\x02\x02\u0190\u0191\x03\x02\x02\x02\u0191\u0194\x03" + + "\x02\x02\x02\u0192\u0190\x03\x02\x02\x02\u0193\u0195\x07\x0F\x02\x02\u0194" + + "\u0193\x03\x02\x02\x02\u0194\u0195\x03\x02\x02\x02\u0195\u0197\x03\x02" + + "\x02\x02\u0196\u0198\x07\f\x02\x02\u0197\u0196\x03\x02\x02\x02\u0197\u0198" + + "\x03\x02\x02\x02\u0198\u0199\x03\x02\x02\x02\u0199\u019A\b\x13\x06\x02" + + "\u019A*\x03\x02\x02\x02\u019B\u019C\x071\x02\x02\u019C\u019D\x07,\x02" + + "\x02\u019D\u01A2\x03\x02\x02\x02\u019E\u01A1\x05+\x14\x02\u019F\u01A1" + + "\v\x02\x02\x02\u01A0\u019E\x03\x02\x02\x02\u01A0\u019F\x03\x02\x02\x02" + + "\u01A1\u01A4\x03\x02\x02\x02\u01A2\u01A3\x03\x02\x02\x02\u01A2\u01A0\x03" + + "\x02\x02\x02\u01A3\u01A5\x03\x02\x02\x02\u01A4\u01A2\x03\x02\x02\x02\u01A5" + + "\u01A6\x07,\x02\x02\u01A6\u01A7\x071\x02\x02\u01A7\u01A8\x03\x02\x02\x02" + + "\u01A8\u01A9\b\x14\x06\x02\u01A9,\x03\x02\x02\x02\u01AA\u01AC\t\x03\x02" + + "\x02\u01AB\u01AA\x03\x02\x02\x02\u01AC\u01AD\x03\x02\x02\x02\u01AD\u01AB" + + "\x03\x02\x02\x02\u01AD\u01AE\x03\x02\x02\x02\u01AE\u01AF\x03\x02\x02\x02" + + "\u01AF\u01B0\b\x15\x06\x02\u01B0.\x03\x02\x02\x02\u01B1\u01B2\x07]\x02" + + "\x02\u01B2\u01B3\x03\x02\x02\x02\u01B3\u01B4\b\x16\x07\x02\u01B4\u01B5" + + "\b\x16\b\x02\u01B50\x03\x02\x02\x02\u01B6\u01B7\x07~\x02\x02\u01B7\u01B8" + + "\x03\x02\x02\x02\u01B8\u01B9\b\x17\t\x02\u01B9\u01BA\b\x17\n\x02\u01BA" + + "2\x03\x02\x02\x02\u01BB\u01BC\x05-\x15\x02\u01BC\u01BD\x03\x02\x02\x02" + + "\u01BD\u01BE\b\x18\x06\x02\u01BE4\x03\x02\x02\x02\u01BF\u01C0\x05)\x13" + + "\x02\u01C0\u01C1\x03\x02\x02\x02\u01C1\u01C2\b\x19\x06\x02\u01C26\x03" + + "\x02\x02\x02\u01C3\u01C4\x05+\x14\x02\u01C4\u01C5\x03\x02\x02\x02\u01C5" + + "\u01C6\b\x1A\x06\x02\u01C68\x03\x02\x02\x02\u01C7\u01C8\x07~\x02\x02\u01C8" + + "\u01C9\x03\x02\x02\x02\u01C9\u01CA\b\x1B\n\x02\u01CA:\x03\x02\x02\x02" + + "\u01CB\u01CC\t\x04\x02\x02\u01CC<\x03\x02\x02\x02\u01CD\u01CE\t\x05\x02" + + "\x02\u01CE>\x03\x02\x02\x02\u01CF\u01D0\x07^\x02\x02\u01D0\u01D1\t\x06" + + "\x02\x02\u01D1@\x03\x02\x02\x02\u01D2\u01D3\n\x07\x02\x02\u01D3B\x03\x02" + + "\x02\x02\u01D4\u01D6\t\b\x02\x02\u01D5\u01D7\t\t\x02\x02\u01D6\u01D5\x03" + + "\x02\x02\x02\u01D6\u01D7\x03\x02\x02\x02\u01D7\u01D9\x03\x02\x02\x02\u01D8" + + "\u01DA\x05;\x1C\x02\u01D9\u01D8\x03\x02\x02\x02\u01DA\u01DB\x03\x02\x02" + + "\x02\u01DB\u01D9\x03\x02\x02\x02\u01DB\u01DC\x03\x02\x02\x02\u01DCD\x03" + + "\x02\x02\x02\u01DD\u01E2\x07$\x02\x02\u01DE\u01E1\x05?\x1E\x02\u01DF\u01E1" + + "\x05A\x1F\x02\u01E0\u01DE\x03\x02\x02\x02\u01E0\u01DF\x03\x02\x02\x02" + + "\u01E1\u01E4\x03\x02\x02\x02\u01E2\u01E0\x03\x02\x02\x02\u01E2\u01E3\x03" + + "\x02\x02\x02\u01E3\u01E5\x03\x02\x02\x02\u01E4\u01E2\x03\x02\x02\x02\u01E5" + + "\u01FB\x07$\x02\x02\u01E6\u01E7\x07$\x02\x02\u01E7\u01E8\x07$\x02\x02" + + "\u01E8\u01E9\x07$\x02\x02\u01E9\u01ED\x03\x02\x02\x02\u01EA\u01EC\n\x02" + + "\x02\x02\u01EB\u01EA\x03\x02\x02\x02\u01EC\u01EF\x03\x02\x02\x02\u01ED" + + "\u01EE\x03\x02\x02\x02\u01ED\u01EB\x03\x02\x02\x02\u01EE\u01F0\x03\x02" + + "\x02\x02\u01EF\u01ED\x03\x02\x02\x02\u01F0\u01F1\x07$\x02\x02\u01F1\u01F2" + + "\x07$\x02\x02\u01F2\u01F3\x07$\x02\x02\u01F3\u01F5\x03\x02\x02\x02\u01F4" + + "\u01F6\x07$\x02\x02\u01F5\u01F4\x03\x02\x02\x02\u01F5\u01F6\x03\x02\x02" + + "\x02\u01F6\u01F8\x03\x02\x02\x02\u01F7\u01F9\x07$\x02\x02\u01F8\u01F7" + + "\x03\x02\x02\x02\u01F8\u01F9\x03\x02\x02\x02\u01F9\u01FB\x03\x02\x02\x02" + + "\u01FA\u01DD\x03\x02\x02\x02\u01FA\u01E6\x03\x02\x02\x02\u01FBF\x03\x02" + + "\x02\x02\u01FC\u01FE\x05;\x1C\x02\u01FD\u01FC\x03\x02\x02\x02\u01FE\u01FF" + + "\x03\x02\x02\x02\u01FF\u01FD\x03\x02\x02\x02\u01FF\u0200\x03\x02\x02\x02" + + "\u0200H\x03\x02\x02\x02\u0201\u0203\x05;\x1C\x02\u0202\u0201\x03\x02\x02" + + "\x02\u0203\u0204\x03\x02\x02\x02\u0204\u0202\x03\x02\x02\x02\u0204\u0205" + + "\x03\x02\x02\x02\u0205\u0206\x03\x02\x02\x02\u0206\u020A\x05U)\x02\u0207" + + "\u0209\x05;\x1C\x02\u0208\u0207\x03\x02\x02\x02\u0209\u020C\x03\x02\x02" + + "\x02\u020A\u0208\x03\x02\x02\x02\u020A\u020B\x03\x02\x02\x02\u020B\u022C" + + "\x03\x02\x02\x02\u020C\u020A\x03\x02\x02\x02\u020D\u020F\x05U)\x02\u020E" + + "\u0210\x05;\x1C\x02\u020F\u020E\x03\x02\x02\x02\u0210\u0211\x03\x02\x02" + + "\x02\u0211\u020F\x03\x02\x02\x02\u0211\u0212\x03\x02\x02\x02\u0212\u022C" + + "\x03\x02\x02\x02\u0213\u0215\x05;\x1C\x02\u0214\u0213\x03\x02\x02\x02" + + "\u0215\u0216\x03\x02\x02\x02\u0216\u0214\x03\x02\x02\x02\u0216\u0217\x03" + + "\x02\x02\x02\u0217\u021F\x03\x02\x02\x02\u0218\u021C\x05U)\x02\u0219\u021B" + + "\x05;\x1C\x02\u021A\u0219\x03\x02\x02\x02\u021B\u021E\x03\x02\x02\x02" + + "\u021C\u021A\x03\x02\x02\x02\u021C\u021D\x03\x02\x02\x02\u021D\u0220\x03" + + "\x02\x02\x02\u021E\u021C\x03\x02\x02\x02\u021F\u0218\x03\x02\x02\x02\u021F" + + "\u0220\x03\x02\x02\x02\u0220\u0221\x03\x02\x02\x02\u0221\u0222\x05C \x02" + + "\u0222\u022C\x03\x02\x02\x02\u0223\u0225\x05U)\x02\u0224\u0226\x05;\x1C" + + "\x02\u0225\u0224\x03\x02\x02\x02\u0226\u0227\x03\x02\x02\x02\u0227\u0225" + + "\x03\x02\x02\x02\u0227\u0228\x03\x02\x02\x02\u0228\u0229\x03\x02\x02\x02" + + "\u0229\u022A\x05C \x02\u022A\u022C\x03\x02\x02\x02\u022B\u0202\x03\x02" + + "\x02\x02\u022B\u020D\x03\x02\x02\x02\u022B\u0214\x03\x02\x02\x02\u022B" + + "\u0223\x03\x02\x02\x02\u022CJ\x03\x02\x02\x02\u022D\u022E\x07d\x02\x02" + + "\u022E\u022F\x07{\x02\x02\u022FL\x03\x02\x02\x02\u0230\u0231\x07{\x02" + + "\x02\u0231\u0232\x07g\x02\x02\u0232\u0233\x07c\x02\x02\u0233\u024D\x07" + + "t\x02\x02\u0234\u0235\x07o\x02\x02\u0235\u0236\x07q\x02\x02\u0236\u0237" + + "\x07p\x02\x02\u0237\u0238\x07v\x02\x02\u0238\u024D\x07j\x02\x02\u0239" + + "\u023A\x07f\x02\x02\u023A\u023B\x07c\x02\x02\u023B\u024D\x07{\x02\x02" + + "\u023C\u023D\x07u\x02\x02\u023D\u023E\x07g\x02\x02\u023E\u023F\x07e\x02" + + "\x02\u023F\u0240\x07q\x02\x02\u0240\u0241\x07p\x02\x02\u0241\u024D\x07" + + "f\x02\x02\u0242\u0243\x07o\x02\x02\u0243\u0244\x07k\x02\x02\u0244\u0245" + + "\x07p\x02\x02\u0245\u0246\x07w\x02\x02\u0246\u0247\x07v\x02\x02\u0247" + + "\u024D\x07g\x02\x02\u0248\u0249\x07j\x02\x02\u0249\u024A\x07q\x02\x02" + + "\u024A\u024B\x07w\x02\x02\u024B\u024D\x07t\x02\x02\u024C\u0230\x03\x02" + + "\x02\x02\u024C\u0234\x03\x02\x02\x02\u024C\u0239\x03\x02\x02\x02\u024C" + + "\u023C\x03\x02\x02\x02\u024C\u0242\x03\x02\x02\x02\u024C\u0248\x03\x02" + + "\x02\x02\u024DN\x03\x02\x02\x02\u024E\u024F\x07c\x02\x02\u024F\u0250\x07" + + "p\x02\x02\u0250\u0251\x07f\x02\x02\u0251P\x03\x02\x02\x02\u0252\u0253" + + "\x07?\x02\x02\u0253R\x03\x02\x02\x02\u0254\u0255\x07.\x02\x02\u0255T\x03" + + "\x02\x02\x02\u0256\u0257\x070\x02\x02\u0257V\x03\x02\x02\x02\u0258\u0259" + + "\x07*\x02\x02\u0259X\x03\x02\x02\x02\u025A\u025B\x07]\x02\x02\u025B\u025C" + + "\x03\x02\x02\x02\u025C\u025D\b+\x02\x02\u025D\u025E\b+\x02\x02\u025EZ" + + "\x03\x02\x02\x02\u025F\u0260\x07_\x02\x02\u0260\u0261\x03\x02\x02\x02" + + "\u0261\u0262\b,\n\x02\u0262\u0263\b,\n\x02\u0263\\\x03\x02\x02\x02\u0264" + + "\u0265\x05\xE5q\x02\u0265\u0266\x05\xE7r\x02\u0266\u0267\x05\xF1w\x02" + + "\u0267^\x03\x02\x02\x02\u0268\u0269\x05\xE1o\x02\u0269\u026A\x05\xDBl" + + "\x02\u026A\u026B\x05\xDFn\x02\u026B\u026C\x05\xD3h\x02\u026C`\x03\x02" + + "\x02\x02\u026D\u026E\x05\xEDu\x02\u026E\u026F\x05\xE1o\x02\u026F\u0270" + + "\x05\xDBl\x02\u0270\u0271\x05\xDFn\x02\u0271\u0272\x05\xD3h\x02\u0272" + + "b\x03\x02\x02\x02\u0273\u0274\x05\xDBl\x02\u0274\u0275\x05\xE5q\x02\u0275" + + "d\x03\x02\x02\x02\u0276\u0277\x05\xDBl\x02\u0277\u0278\x05\xEFv\x02\u0278" + + "f\x03\x02\x02\x02\u0279\u027A\x05\xCBd\x02\u027A\u027B\x05\xEFv\x02\u027B" + + "h\x03\x02\x02\x02\u027C\u027D\x05\xE5q\x02\u027D\u027E\x05\xF3x\x02\u027E" + + "\u027F\x05\xE1o\x02\u027F\u0280\x05\xE1o\x02\u0280j\x03\x02\x02\x02\u0281" + + "\u0282\x07q\x02\x02\u0282\u0283\x07t\x02\x02\u0283l\x03\x02\x02\x02\u0284" + + "\u0285\x07+\x02\x02\u0285n\x03\x02\x02\x02\u0286\u0287\x07a\x02\x02\u0287" + + "p\x03\x02\x02\x02\u0288\u0289\x07k\x02\x02\u0289\u028A\x07p\x02\x02\u028A" + + "\u028B\x07h\x02\x02\u028B\u028C\x07q\x02\x02\u028Cr\x03\x02\x02\x02\u028D" + + "\u028E\x07h\x02\x02\u028E\u028F\x07w\x02\x02\u028F\u0290\x07p\x02\x02" + + "\u0290\u0291\x07e\x02\x02\u0291\u0292\x07v\x02\x02\u0292\u0293\x07k\x02" + + "\x02\u0293\u0294\x07q\x02\x02\u0294\u0295\x07p\x02\x02\u0295\u0296\x07" + + "u\x02\x02\u0296t\x03\x02\x02\x02\u0297\u0298\x07v\x02\x02\u0298\u0299" + + "\x07t\x02\x02\u0299\u029A\x07w\x02\x02\u029A\u02A1\x07g\x02\x02\u029B" + + "\u029C\x07h\x02\x02\u029C\u029D\x07c\x02\x02\u029D\u029E\x07n\x02\x02" + + "\u029E\u029F\x07u\x02\x02\u029F\u02A1\x07g\x02\x02\u02A0\u0297\x03\x02" + + "\x02\x02\u02A0\u029B\x03\x02\x02\x02\u02A1v\x03\x02\x02\x02\u02A2\u02A3" + + "\x07?\x02\x02\u02A3\u02AD\x07?\x02\x02\u02A4\u02A5\x07#\x02\x02\u02A5" + + "\u02AD\x07?\x02\x02\u02A6\u02AD\x07>\x02\x02\u02A7\u02A8\x07>\x02\x02" + + "\u02A8\u02AD\x07?\x02\x02\u02A9\u02AD\x07@\x02\x02\u02AA\u02AB\x07@\x02" + + "\x02\u02AB\u02AD\x07?\x02\x02\u02AC\u02A2\x03\x02\x02\x02\u02AC\u02A4" + + "\x03\x02\x02\x02\u02AC\u02A6\x03\x02\x02\x02\u02AC\u02A7\x03\x02\x02\x02" + + "\u02AC\u02A9\x03\x02\x02\x02\u02AC\u02AA\x03\x02\x02\x02\u02ADx\x03\x02" + + "\x02\x02\u02AE\u02AF\x07-\x02\x02\u02AFz\x03\x02\x02\x02\u02B0\u02B1\x07" + + "/\x02\x02\u02B1|\x03\x02\x02\x02\u02B2\u02B3\x07,\x02\x02\u02B3~\x03\x02" + + "\x02\x02\u02B4\u02B5\x071\x02\x02\u02B5\x80\x03\x02\x02\x02\u02B6\u02B7" + + "\x07\'\x02\x02\u02B7\x82\x03\x02\x02\x02\u02B8\u02B9\x073\x02\x02\u02B9" + + "\u02BA\x072\x02\x02\u02BA\x84\x03\x02\x02\x02\u02BB\u02BC\x07c\x02\x02" + + "\u02BC\u02BD\x07u\x02\x02\u02BD\u02C3\x07e\x02\x02\u02BE\u02BF\x07f\x02" + + "\x02\u02BF\u02C0\x07g\x02\x02\u02C0\u02C1\x07u\x02\x02\u02C1\u02C3\x07" + + "e\x02\x02\u02C2\u02BB\x03\x02\x02\x02\u02C2\u02BE\x03\x02\x02\x02\u02C3" + + "\x86\x03\x02\x02\x02\u02C4\u02C5\x07p\x02\x02\u02C5\u02C6\x07w\x02\x02" + + "\u02C6\u02C7\x07n\x02\x02\u02C7\u02C8\x07n\x02\x02\u02C8\u02C9\x07u\x02" + + "\x02\u02C9\x88\x03\x02\x02\x02\u02CA\u02CB\x07h\x02\x02\u02CB\u02CC\x07" + + "k\x02\x02\u02CC\u02CD\x07t\x02\x02\u02CD\u02CE\x07u\x02\x02\u02CE\u02D4" + + "\x07v\x02\x02\u02CF\u02D0\x07n\x02\x02\u02D0\u02D1\x07c\x02\x02\u02D1" + + "\u02D2\x07u\x02\x02\u02D2\u02D4\x07v\x02\x02\u02D3\u02CA\x03\x02\x02\x02" + + "\u02D3\u02CF\x03\x02\x02\x02\u02D4\x8A\x03\x02\x02\x02\u02D5\u02D6\x05" + + "\xEDu\x02\u02D6\u02D7\x05\xE7r\x02\u02D7\u02D8\x05\xF3x\x02\u02D8\u02D9" + + "\x05\xE5q\x02\u02D9\u02DA\x05\xD1g\x02\u02DA\u0440\x03\x02\x02\x02\u02DB" + + "\u02DC\x05\xCBd\x02\u02DC\u02DD\x05\xCDe\x02\u02DD\u02DE\x05\xEFv\x02" + + "\u02DE\u0440\x03\x02\x02\x02\u02DF\u02E0\x05\xE9s\x02\u02E0\u02E1\x05" + + "\xE7r\x02\u02E1\u02E2\x05\xF7z\x02\u02E2\u0440\x03\x02\x02\x02\u02E3\u02E4" + + "\x05\xE1o\x02\u02E4\u02E5\x05\xE7r\x02\u02E5\u02E6\x05\xD7j\x02\u02E6" + + "\u02E7\x05\x83@\x02\u02E7\u0440\x03\x02\x02\x02\u02E8\u02E9\x05\xE9s\x02" + + "\u02E9\u02EA\x05\xDBl\x02\u02EA\u0440\x03\x02\x02\x02\u02EB\u02EC\x05" + + "\xF1w\x02\u02EC\u02ED\x05\xCBd\x02\u02ED\u02EE\x05\xF3x\x02\u02EE\u0440" + + "\x03\x02\x02\x02\u02EF\u0440\x05\xD3h\x02\u02F0\u02F1\x05\xEFv\x02\u02F1" + + "\u02F2\x05\xF3x\x02\u02F2\u02F3\x05\xCDe\x02\u02F3\u02F4\x05\xEFv\x02" + + "\u02F4\u02F5\x05\xF1w\x02\u02F5\u02F6\x05\xEDu\x02\u02F6\u02F7\x05\xDB" + + "l\x02\u02F7\u02F8\x05\xE5q\x02\u02F8\u02F9\x05\xD7j\x02\u02F9\u0440\x03" + + "\x02\x02\x02\u02FA\u02FB\x05\xF1w\x02\u02FB\u02FC\x05\xEDu\x02\u02FC\u02FD" + + "\x05\xDBl\x02\u02FD\u02FE\x05\xE3p\x02\u02FE\u0440\x03\x02\x02\x02\u02FF" + + "\u0300\x05\xCFf\x02\u0300\u0301\x05\xE7r\x02\u0301\u0302\x05\xE5q\x02" + + "\u0302\u0303\x05\xCFf\x02\u0303\u0304\x05\xCBd\x02\u0304\u0305\x05\xF1" + + "w\x02\u0305\u0440\x03\x02\x02\x02\u0306\u0307\x05\xEFv\x02\u0307\u0308" + + "\x05\xF1w\x02\u0308\u0309\x05\xCBd\x02\u0309\u030A\x05\xEDu\x02\u030A" + + "\u030B\x05\xF1w\x02\u030B\u030C\x05\xEFv\x02\u030C\u030D\x05o6\x02\u030D" + + "\u030E\x05\xF7z\x02\u030E\u030F\x05\xDBl\x02\u030F\u0310\x05\xF1w\x02" + + "\u0310\u0311\x05\xD9k\x02\u0311\u0440\x03\x02\x02\x02\u0312\u0313\x05" + + "\xD1g\x02\u0313\u0314\x05\xCBd\x02\u0314\u0315\x05\xF1w\x02\u0315\u0316" + + "\x05\xD3h\x02\u0316\u0317\x05o6\x02\u0317\u0318\x05\xD5i\x02\u0318\u0319" + + "\x05\xE7r\x02\u0319\u031A\x05\xEDu\x02\u031A\u031B\x05\xE3p\x02\u031B" + + "\u031C\x05\xCBd\x02\u031C\u031D\x05\xF1w\x02\u031D\u0440\x03\x02\x02\x02" + + "\u031E\u031F\x05\xD1g\x02\u031F\u0320\x05\xCBd\x02\u0320\u0321\x05\xF1" + + "w\x02\u0321\u0322\x05\xD3h\x02\u0322\u0323\x05o6\x02\u0323\u0324\x05\xF1" + + "w\x02\u0324\u0325\x05\xEDu\x02\u0325\u0326\x05\xF3x\x02\u0326\u0327\x05" + + "\xE5q\x02\u0327\u0328\x05\xCFf\x02\u0328\u0440\x03\x02\x02\x02\u0329\u032A" + + "\x05\xD1g\x02\u032A\u032B\x05\xCBd\x02\u032B\u032C\x05\xF1w\x02\u032C" + + "\u032D\x05\xD3h\x02\u032D\u032E\x05o6\x02\u032E\u032F\x05\xE9s\x02\u032F" + + "\u0330\x05\xCBd\x02\u0330\u0331\x05\xEDu\x02\u0331\u0332\x05\xEFv\x02" + + "\u0332\u0333\x05\xD3h\x02\u0333\u0440\x03\x02\x02\x02\u0334\u0335\x05" + + "\xCBd\x02\u0335\u0336\x05\xF3x\x02\u0336\u0337\x05\xF1w\x02\u0337\u0338" + + "\x05\xE7r\x02\u0338\u0339\x05o6\x02\u0339\u033A\x05\xCDe\x02\u033A\u033B" + + "\x05\xF3x\x02\u033B\u033C\x05\xCFf\x02\u033C\u033D\x05\xDFn\x02\u033D" + + "\u033E\x05\xD3h\x02\u033E\u033F\x05\xF1w\x02\u033F\u0440\x03\x02\x02\x02" + + "\u0340\u0341\x05\xDBl\x02\u0341\u0342\x05\xEFv\x02\u0342\u0343\x05o6\x02" + + "\u0343\u0344\x05\xD5i\x02\u0344\u0345\x05\xDBl\x02\u0345\u0346\x05\xE5" + + "q\x02\u0346\u0347\x05\xDBl\x02\u0347\u0348\x05\xF1w\x02\u0348\u0349\x05" + + "\xD3h\x02\u0349\u0440\x03\x02\x02\x02\u034A\u034B\x05\xDBl\x02\u034B\u034C" + + "\x05\xEFv\x02\u034C\u034D\x05o6\x02\u034D\u034E\x05\xDBl\x02\u034E\u034F" + + "\x05\xE5q\x02\u034F\u0350\x05\xD5i\x02\u0350\u0351\x05\xDBl\x02\u0351" + + "\u0352\x05\xE5q\x02\u0352\u0353\x05\xDBl\x02\u0353\u0354\x05\xF1w\x02" + + "\u0354\u0355\x05\xD3h\x02\u0355\u0440\x03\x02\x02\x02\u0356\u0357\x05" + + "\xCFf\x02\u0357\u0358\x05\xCBd\x02\u0358\u0359\x05\xEFv\x02\u0359\u035A" + + "\x05\xD3h\x02\u035A\u0440\x03\x02\x02\x02\u035B\u035C\x05\xE1o\x02\u035C" + + "\u035D\x05\xD3h\x02\u035D\u035E\x05\xE5q\x02\u035E\u035F\x05\xD7j\x02" + + "\u035F\u0360\x05\xF1w\x02\u0360\u0361\x05\xD9k\x02\u0361\u0440\x03\x02" + + "\x02\x02\u0362\u0363\x05\xE3p\x02\u0363\u0364\x05\xF5y\x02\u0364\u0365" + + "\x05o6\x02\u0365\u0366\x05\xE3p\x02\u0366\u0367\x05\xCBd\x02\u0367\u0368" + + "\x05\xF9{\x02\u0368\u0440\x03\x02\x02\x02\u0369\u036A\x05\xE3p\x02\u036A" + + "\u036B\x05\xF5y\x02\u036B\u036C\x05o6\x02\u036C\u036D\x05\xE3p\x02\u036D" + + "\u036E\x05\xDBl\x02\u036E\u036F\x05\xE5q\x02\u036F\u0440\x03\x02\x02\x02" + + "\u0370\u0371\x05\xE3p\x02\u0371\u0372\x05\xF5y\x02\u0372\u0373\x05o6\x02" + + "\u0373\u0374\x05\xCBd\x02\u0374\u0375\x05\xF5y\x02\u0375\u0376\x05\xD7" + + "j\x02\u0376\u0440\x03\x02\x02\x02\u0377\u0378\x05\xE3p\x02\u0378\u0379" + + "\x05\xF5y\x02\u0379\u037A\x05o6\x02\u037A\u037B\x05\xEFv\x02\u037B\u037C" + + "\x05\xF3x\x02\u037C\u037D\x05\xE3p\x02\u037D\u0440\x03\x02\x02\x02\u037E" + + "\u037F\x05\xE3p\x02\u037F\u0380\x05\xF5y\x02\u0380\u0381\x05o6\x02\u0381" + + "\u0382\x05\xCFf\x02\u0382\u0383\x05\xE7r\x02\u0383\u0384\x05\xF3x\x02" + + "\u0384\u0385\x05\xE5q\x02\u0385\u0386\x05\xF1w\x02\u0386\u0440\x03\x02" + + "\x02\x02\u0387\u0388\x05\xE3p\x02\u0388\u0389\x05\xF5y\x02\u0389\u038A" + + "\x05o6\x02\u038A\u038B\x05\xCFf\x02\u038B\u038C\x05\xE7r\x02\u038C\u038D" + + "\x05\xE5q\x02\u038D\u038E\x05\xCFf\x02\u038E\u038F\x05\xCBd\x02\u038F" + + "\u0390\x05\xF1w\x02\u0390\u0440\x03\x02\x02\x02\u0391\u0392\x05\xE3p\x02" + + "\u0392\u0393\x05\xF5y\x02\u0393\u0394\x05o6\x02\u0394\u0395\x05\xDDm\x02" + + "\u0395\u0396\x05\xE7r\x02\u0396\u0397\x05\xDBl\x02\u0397\u0398\x05\xE5" + + "q\x02\u0398\u0440\x03\x02\x02\x02\u0399\u039A\x05\xE3p\x02\u039A\u039B" + + "\x05\xF5y\x02\u039B\u039C\x05o6\x02\u039C\u039D\x05\xE3p\x02\u039D\u039E" + + "\x05\xD3h\x02\u039E\u039F\x05\xD1g\x02\u039F\u03A0\x05\xDBl\x02\u03A0" + + "\u03A1\x05\xCBd\x02\u03A1\u03A2\x05\xE5q\x02\u03A2\u0440\x03\x02\x02\x02" + + "\u03A3\u03A4\x05\xE3p\x02\u03A4\u03A5\x05\xF5y\x02\u03A5\u03A6\x05o6\x02" + + "\u03A6\u03A7\x05\xD1g\x02\u03A7\u03A8\x05\xD3h\x02\u03A8\u03A9\x05\xD1" + + "g\x02\u03A9\u03AA\x05\xF3x\x02\u03AA\u03AB\x05\xE9s\x02\u03AB\u03AC\x05" + + "\xD3h\x02\u03AC\u0440\x03\x02\x02\x02\u03AD\u03AE\x05\xE3p\x02\u03AE\u03AF" + + "\x05\xD3h\x02\u03AF\u03B0\x05\xF1w\x02\u03B0\u03B1\x05\xCBd\x02\u03B1" + + "\u03B2\x05\xD1g\x02\u03B2\u03B3\x05\xCBd\x02\u03B3\u03B4\x05\xF1w\x02" + + "\u03B4\u03B5\x05\xCBd\x02\u03B5\u0440\x03\x02\x02\x02\u03B6\u03B7\x05" + + "\xEFv\x02\u03B7\u03B8\x05\xE9s\x02\u03B8\u03B9\x05\xE1o\x02\u03B9\u03BA" + + "\x05\xDBl\x02\u03BA\u03BB\x05\xF1w\x02\u03BB\u0440\x03\x02\x02\x02\u03BC" + + "\u03BD\x05\xF1w\x02\u03BD\u03BE\x05\xE7r\x02\u03BE\u03BF\x05o6\x02\u03BF" + + "\u03C0\x05\xEFv\x02\u03C0\u03C1\x05\xF1w\x02\u03C1\u03C2\x05\xEDu\x02" + + "\u03C2\u03C3\x05\xDBl\x02\u03C3\u03C4\x05\xE5q\x02\u03C4\u03C5\x05\xD7" + + "j\x02\u03C5\u0440\x03\x02\x02\x02\u03C6\u03C7\x05\xF1w\x02\u03C7\u03C8" + + "\x05\xE7r\x02\u03C8\u03C9\x05o6\x02\u03C9\u03CA\x05\xEFv\x02\u03CA\u03CB" + + "\x05\xF1w\x02\u03CB\u03CC\x05\xEDu\x02\u03CC\u0440\x03\x02\x02\x02\u03CD" + + "\u03CE\x05\xF1w\x02\u03CE\u03CF\x05\xE7r\x02\u03CF\u03D0\x05o6\x02\u03D0" + + "\u03D1\x05\xCDe\x02\u03D1\u03D2\x05\xE7r\x02\u03D2\u03D3\x05\xE7r\x02" + + "\u03D3\u03D4\x05\xE1o\x02\u03D4\u0440\x03\x02\x02\x02\u03D5\u03D6\x05" + + "\xF1w\x02\u03D6\u03D7\x05\xE7r\x02\u03D7\u03D8\x05o6\x02\u03D8\u03D9\x05" + + "\xCDe\x02\u03D9\u03DA\x05\xE7r\x02\u03DA\u03DB\x05\xE7r\x02\u03DB\u03DC" + + "\x05\xE1o\x02\u03DC\u03DD\x05\xD3h\x02\u03DD\u03DE\x05\xCBd\x02\u03DE" + + "\u03DF\x05\xE5q\x02\u03DF\u0440\x03\x02\x02\x02\u03E0\u03E1\x05\xF1w\x02" + + "\u03E1\u03E2\x05\xE7r\x02\u03E2\u03E3\x05o6\x02\u03E3\u03E4\x05\xD1g\x02" + + "\u03E4\u03E5\x05\xCBd\x02\u03E5\u03E6\x05\xF1w\x02\u03E6\u03E7\x05\xD3" + + "h\x02\u03E7\u03E8\x05\xF1w\x02\u03E8\u03E9\x05\xDBl\x02\u03E9\u03EA\x05" + + "\xE3p\x02\u03EA\u03EB\x05\xD3h\x02\u03EB\u0440\x03\x02\x02\x02\u03EC\u03ED" + + "\x05\xF1w\x02\u03ED\u03EE\x05\xE7r\x02\u03EE\u03EF\x05o6\x02\u03EF\u03F0" + + "\x05\xD1g\x02\u03F0\u03F1\x05\xF1w\x02\u03F1\u0440\x03\x02\x02\x02\u03F2" + + "\u03F3\x05\xF1w\x02\u03F3\u03F4\x05\xE7r\x02\u03F4\u03F5\x05o6\x02\u03F5" + + "\u03F6\x05\xD1g\x02\u03F6\u03F7\x05\xCDe\x02\u03F7\u03F8\x05\xE1o\x02" + + "\u03F8\u0440\x03\x02\x02\x02\u03F9\u03FA\x05\xF1w\x02\u03FA\u03FB\x05" + + "\xE7r\x02\u03FB\u03FC\x05o6\x02\u03FC\u03FD\x05\xD1g\x02\u03FD\u03FE\x05" + + "\xE7r\x02\u03FE\u03FF\x05\xF3x\x02\u03FF\u0400\x05\xCDe\x02\u0400\u0401" + + "\x05\xE1o\x02\u0401\u0402\x05\xD3h\x02\u0402\u0440\x03\x02\x02\x02\u0403" + + "\u0404\x05\xF1w\x02\u0404\u0405\x05\xE7r\x02\u0405\u0406\x05o6\x02\u0406" + + "\u0407\x05\xDBl\x02\u0407\u0408\x05\xE5q\x02\u0408\u0409\x05\xF1w\x02" + + "\u0409\u0440\x03\x02\x02\x02\u040A\u040B\x05\xF1w\x02\u040B\u040C\x05" + + "\xE7r\x02\u040C\u040D\x05o6\x02\u040D\u040E\x05\xDBl\x02\u040E\u040F\x05" + + "\xE5q\x02\u040F\u0410\x05\xF1w\x02\u0410\u0411\x05\xD3h\x02\u0411\u0412" + + "\x05\xD7j\x02\u0412\u0413\x05\xD3h\x02\u0413\u0414\x05\xEDu\x02\u0414" + + "\u0440\x03\x02\x02\x02\u0415\u0416\x05\xF1w\x02\u0416\u0417\x05\xE7r\x02" + + "\u0417\u0418\x05o6\x02\u0418\u0419\x05\xE1o\x02\u0419\u041A\x05\xE7r\x02" + + "\u041A\u041B\x05\xE5q\x02\u041B\u041C\x05\xD7j\x02\u041C\u0440\x03\x02" + + "\x02\x02\u041D\u041E\x05\xF1w\x02\u041E\u041F\x05\xE7r\x02\u041F\u0420" + + "\x05o6\x02\u0420\u0421\x05\xDBl\x02\u0421\u0422\x05\xE9s\x02\u0422\u0440" + + "\x03\x02\x02\x02\u0423\u0424\x05\xF1w\x02\u0424\u0425\x05\xE7r\x02\u0425" + + "\u0426\x05o6\x02\u0426\u0427\x05\xF5y\x02\u0427\u0428\x05\xD3h\x02\u0428" + + "\u0429\x05\xEDu\x02\u0429\u042A\x05\xEFv\x02\u042A\u042B\x05\xDBl\x02" + + "\u042B\u042C\x05\xE7r\x02\u042C\u042D\x05\xE5q\x02\u042D\u0440\x03\x02" + + "\x02\x02\u042E\u042F\x05\xF1w\x02\u042F\u0430\x05\xE7r\x02\u0430\u0431" + + "\x05o6\x02\u0431\u0432\x05\xF3x\x02\u0432\u0433\x05\xE5q\x02\u0433\u0434" + + "\x05\xEFv\x02\u0434\u0435\x05\xDBl\x02\u0435\u0436\x05\xD7j\x02\u0436" + + "\u0437\x05\xE5q\x02\u0437\u0438\x05\xD3h\x02\u0438\u0439\x05\xD1g\x02" + + "\u0439\u043A\x05o6\x02\u043A\u043B\x05\xE1o\x02\u043B\u043C\x05\xE7r\x02" + + "\u043C\u043D\x05\xE5q\x02\u043D\u043E\x05\xD7j\x02\u043E\u0440\x03\x02" + + "\x02"; + private static readonly _serializedATNSegment2: string = + "\x02\u043F\u02D5\x03\x02\x02\x02\u043F\u02DB\x03\x02\x02\x02\u043F\u02DF" + + "\x03\x02\x02\x02\u043F\u02E3\x03\x02\x02\x02\u043F\u02E8\x03\x02\x02\x02" + + "\u043F\u02EB\x03\x02\x02\x02\u043F\u02EF\x03\x02\x02\x02\u043F\u02F0\x03" + + "\x02\x02\x02\u043F\u02FA\x03\x02\x02\x02\u043F\u02FF\x03\x02\x02\x02\u043F" + + "\u0306\x03\x02\x02\x02\u043F\u0312\x03\x02\x02\x02\u043F\u031E\x03\x02" + + "\x02\x02\u043F\u0329\x03\x02\x02\x02\u043F\u0334\x03\x02\x02\x02\u043F" + + "\u0340\x03\x02\x02\x02\u043F\u034A\x03\x02\x02\x02\u043F\u0356\x03\x02" + + "\x02\x02\u043F\u035B\x03\x02\x02\x02\u043F\u0362\x03\x02\x02\x02\u043F" + + "\u0369\x03\x02\x02\x02\u043F\u0370\x03\x02\x02\x02\u043F\u0377\x03\x02" + + "\x02\x02\u043F\u037E\x03\x02\x02\x02\u043F\u0387\x03\x02\x02\x02\u043F" + + "\u0391\x03\x02\x02\x02\u043F\u0399\x03\x02\x02\x02\u043F\u03A3\x03\x02" + + "\x02\x02\u043F\u03AD\x03\x02\x02\x02\u043F\u03B6\x03\x02\x02\x02\u043F" + + "\u03BC\x03\x02\x02\x02\u043F\u03C6\x03\x02\x02\x02\u043F\u03CD\x03\x02" + + "\x02\x02\u043F\u03D5\x03\x02\x02\x02\u043F\u03E0\x03\x02\x02\x02\u043F" + + "\u03EC\x03\x02\x02\x02\u043F\u03F2\x03\x02\x02\x02\u043F\u03F9\x03\x02" + + "\x02\x02\u043F\u0403\x03\x02\x02\x02\u043F\u040A\x03\x02\x02\x02\u043F" + + "\u0415\x03\x02\x02\x02\u043F\u041D\x03\x02\x02\x02\u043F\u0423\x03\x02" + + "\x02\x02\u043F\u042E\x03\x02\x02\x02\u0440\x8C\x03\x02\x02\x02\u0441\u0442" + + "\x05\xCBd\x02\u0442\u0443\x05\xF5y\x02\u0443\u0444\x05\xD7j\x02\u0444" + + "\u0493\x03\x02\x02\x02\u0445\u0446\x05\xE3p\x02\u0446\u0447\x05\xDBl\x02" + + "\u0447\u0448\x05\xE5q\x02\u0448\u0493\x03\x02\x02\x02\u0449\u044A\x05" + + "\xE3p\x02\u044A\u044B\x05\xCBd\x02\u044B\u044C\x05\xF9{\x02\u044C\u0493" + + "\x03\x02\x02\x02\u044D\u044E\x05\xEFv\x02\u044E\u044F\x05\xF3x\x02\u044F" + + "\u0450\x05\xE3p\x02\u0450\u0493\x03\x02\x02\x02\u0451\u0452\x05\xCFf\x02" + + "\u0452\u0453\x05\xE7r\x02\u0453\u0454\x05\xF3x\x02\u0454\u0455\x05\xE5" + + "q\x02\u0455\u0456\x05\xF1w\x02\u0456\u0493\x03\x02\x02\x02\u0457\u0458" + + "\x05\xCFf\x02\u0458\u0459\x05\xE7r\x02\u0459\u045A\x05\xF3x\x02\u045A" + + "\u045B\x05\xE5q\x02\u045B\u045C\x05\xF1w\x02\u045C\u045D\x05o6\x02\u045D" + + "\u045E\x05\xD1g\x02\u045E\u045F\x05\xDBl\x02\u045F\u0460\x05\xEFv\x02" + + "\u0460\u0461\x05\xF1w\x02\u0461\u0462\x05\xDBl\x02\u0462\u0463\x05\xE5" + + "q\x02\u0463\u0464\x05\xCFf\x02\u0464\u0465\x05\xF1w\x02\u0465\u0493\x03" + + "\x02\x02\x02\u0466\u0467\x05\xE9s\x02\u0467\u0468\x05\xD3h\x02\u0468\u0469" + + "\x05\xEDu\x02\u0469\u046A\x05\xCFf\x02\u046A\u046B\x05\xD3h\x02\u046B" + + "\u046C\x05\xE5q\x02\u046C\u046D\x05\xF1w\x02\u046D\u046E\x05\xDBl\x02" + + "\u046E\u046F\x05\xE1o\x02\u046F\u0470\x05\xD3h\x02\u0470\u0493\x03\x02" + + "\x02\x02\u0471\u0472\x05\xE3p\x02\u0472\u0473\x05\xD3h\x02\u0473\u0474" + + "\x05\xD1g\x02\u0474\u0475\x05\xDBl\x02\u0475\u0476\x05\xCBd\x02\u0476" + + "\u0477\x05\xE5q\x02\u0477\u0493\x03\x02\x02\x02\u0478\u0479\x05\xE3p\x02" + + "\u0479\u047A\x05\xD3h\x02\u047A\u047B\x05\xD1g\x02\u047B\u047C\x05\xDB" + + "l\x02\u047C\u047D\x05\xCBd\x02\u047D\u047E\x05\xE5q\x02\u047E\u047F\x05" + + "o6\x02\u047F\u0480\x05\xCBd\x02\u0480\u0481\x05\xCDe\x02\u0481\u0482\x05" + + "\xEFv\x02\u0482\u0483\x05\xE7r\x02\u0483\u0484\x05\xE1o\x02\u0484\u0485" + + "\x05\xF3x\x02\u0485\u0486\x05\xF1w\x02\u0486\u0487\x05\xD3h\x02\u0487" + + "\u0488\x05o6\x02\u0488\u0489\x05\xD1g\x02\u0489\u048A\x05\xD3h\x02\u048A" + + "\u048B\x05\xF5y\x02\u048B\u048C\x05\xDBl\x02\u048C\u048D\x05\xCBd\x02" + + "\u048D\u048E\x05\xF1w\x02\u048E\u048F\x05\xDBl\x02\u048F\u0490\x05\xE7" + + "r\x02\u0490\u0491\x05\xE5q\x02\u0491\u0493\x03\x02\x02\x02\u0492\u0441" + + "\x03\x02\x02\x02\u0492\u0445\x03\x02\x02\x02\u0492\u0449\x03\x02\x02\x02" + + "\u0492\u044D\x03\x02\x02\x02\u0492\u0451\x03\x02\x02\x02\u0492\u0457\x03" + + "\x02\x02\x02\u0492\u0466\x03\x02\x02\x02\u0492\u0471\x03\x02\x02\x02\u0492" + + "\u0478\x03\x02\x02\x02\u0493\x8E\x03\x02\x02\x02\u0494\u0495\x05\xCFf" + + "\x02\u0495\u0496\x05\xDBl\x02\u0496\u0497\x05\xD1g\x02\u0497\u0498\x05" + + "\xEDu\x02\u0498\u0499\x05o6\x02\u0499\u049A\x05\xE3p\x02\u049A\u049B\x05" + + "\xCBd\x02\u049B\u049C\x05\xF1w\x02\u049C\u049D\x05\xCFf\x02\u049D\u049E" + + "\x05\xD9k\x02\u049E\x90\x03\x02\x02\x02\u049F\u04A6\x05=\x1D\x02\u04A0" + + "\u04A5\x05=\x1D\x02\u04A1\u04A5\x05;\x1C\x02\u04A2\u04A5\x07a\x02\x02" + + "\u04A3\u04A5\x05}=\x02\u04A4\u04A0\x03\x02\x02\x02\u04A4\u04A1\x03\x02" + + "\x02\x02\u04A4\u04A2\x03\x02\x02\x02\u04A4\u04A3\x03\x02\x02\x02\u04A5" + + "\u04A8\x03\x02\x02\x02\u04A6\u04A4\x03\x02\x02\x02\u04A6\u04A7\x03\x02" + + "\x02\x02\u04A7\u04B3\x03\x02\x02\x02\u04A8\u04A6\x03\x02\x02\x02\u04A9" + + "\u04AE\t\n\x02\x02\u04AA\u04AF\x05=\x1D\x02\u04AB\u04AF\x05;\x1C\x02\u04AC" + + "\u04AF\x07a\x02\x02\u04AD\u04AF\x05}=\x02\u04AE\u04AA\x03\x02\x02\x02" + + "\u04AE\u04AB\x03\x02\x02\x02\u04AE\u04AC\x03\x02\x02\x02\u04AE\u04AD\x03" + + "\x02\x02\x02\u04AF\u04B0\x03\x02\x02\x02\u04B0\u04AE\x03\x02\x02\x02\u04B0" + + "\u04B1\x03\x02\x02\x02\u04B1\u04B3\x03\x02\x02\x02\u04B2\u049F\x03\x02" + + "\x02\x02\u04B2\u04A9\x03\x02\x02\x02\u04B3\x92\x03\x02\x02\x02\u04B4\u04BA" + + "\x07b\x02\x02\u04B5\u04B9\n\v\x02\x02\u04B6\u04B7\x07b\x02\x02\u04B7\u04B9" + + "\x07b\x02\x02\u04B8\u04B5\x03\x02\x02\x02\u04B8\u04B6\x03\x02\x02\x02" + + "\u04B9\u04BC\x03\x02\x02\x02\u04BA\u04B8\x03\x02\x02\x02\u04BA\u04BB\x03" + + "\x02\x02\x02\u04BB\u04BD\x03\x02\x02\x02\u04BC\u04BA\x03\x02\x02\x02\u04BD" + + "\u04BE\x07b\x02\x02\u04BE\x94\x03\x02\x02\x02\u04BF\u04C0\x05)\x13\x02" + + "\u04C0\u04C1\x03\x02\x02\x02\u04C1\u04C2\bI\x06\x02\u04C2\x96\x03\x02" + + "\x02\x02\u04C3\u04C4\x05+\x14\x02\u04C4\u04C5\x03\x02\x02\x02\u04C5\u04C6" + + "\bJ\x06\x02\u04C6\x98\x03\x02\x02\x02\u04C7\u04C8\x05-\x15\x02\u04C8\u04C9" + + "\x03\x02\x02\x02\u04C9\u04CA\bK\x06\x02\u04CA\x9A\x03\x02\x02\x02\u04CB" + + "\u04CC\x07~\x02\x02\u04CC\u04CD\x03\x02\x02\x02\u04CD\u04CE\bL\t\x02\u04CE" + + "\u04CF\bL\n\x02\u04CF\x9C\x03\x02\x02\x02\u04D0\u04D1\x07]\x02\x02\u04D1" + + "\u04D2\x03\x02\x02\x02\u04D2\u04D3\bM\x07\x02\u04D3\u04D4\bM\x04\x02\u04D4" + + "\u04D5\bM\x04\x02\u04D5\x9E\x03\x02\x02\x02\u04D6\u04D7\x07_\x02\x02\u04D7" + + "\u04D8\x03\x02\x02\x02\u04D8\u04D9\bN\n\x02\u04D9\u04DA\bN\n\x02\u04DA" + + "\u04DB\bN\v\x02\u04DB\xA0\x03\x02\x02\x02\u04DC\u04DD\x07.\x02\x02\u04DD" + + "\u04DE\x03\x02\x02\x02\u04DE\u04DF\bO\f\x02\u04DF\xA2\x03\x02\x02\x02" + + "\u04E0\u04E1\x07?\x02\x02\u04E1\u04E2\x03\x02\x02\x02\u04E2\u04E3\bP\r" + + "\x02\u04E3\xA4\x03\x02\x02\x02\u04E4\u04E5\x05\xE3p\x02\u04E5\u04E6\x05" + + "\xD3h\x02\u04E6\u04E7\x05\xF1w\x02\u04E7\u04E8\x05\xCBd\x02\u04E8\u04E9" + + "\x05\xD1g\x02\u04E9\u04EA\x05\xCBd\x02\u04EA\u04EB\x05\xF1w\x02\u04EB" + + "\u04EC\x05\xCBd\x02\u04EC\xA6\x03\x02\x02\x02\u04ED\u04EF\x05\xA9S\x02" + + "\u04EE\u04ED\x03\x02\x02\x02\u04EF\u04F0\x03\x02\x02\x02\u04F0\u04EE\x03" + + "\x02\x02\x02\u04F0\u04F1\x03\x02\x02\x02\u04F1\xA8\x03\x02\x02\x02\u04F2" + + "\u04F4\n\f\x02\x02\u04F3\u04F2\x03\x02\x02\x02\u04F4\u04F5\x03\x02\x02" + + "\x02\u04F5\u04F3\x03\x02\x02\x02\u04F5\u04F6\x03\x02\x02\x02\u04F6\u04FA" + + "\x03\x02\x02\x02\u04F7\u04F8\x071\x02\x02\u04F8\u04FA\n\r\x02\x02\u04F9" + + "\u04F3\x03\x02\x02\x02\u04F9\u04F7\x03\x02\x02\x02\u04FA\xAA\x03\x02\x02" + + "\x02\u04FB\u04FC\x05\x93H\x02\u04FC\xAC\x03\x02\x02\x02\u04FD\u04FE\x05" + + ")\x13\x02\u04FE\u04FF\x03\x02\x02\x02\u04FF\u0500\bU\x06\x02\u0500\xAE" + + "\x03\x02\x02\x02\u0501\u0502\x05+\x14\x02\u0502\u0503\x03\x02\x02\x02" + + "\u0503\u0504\bV\x06\x02\u0504\xB0\x03\x02\x02\x02\u0505\u0506\x05-\x15" + + "\x02\u0506\u0507\x03\x02\x02\x02\u0507\u0508\bW\x06\x02\u0508\xB2\x03" + + "\x02\x02\x02\u0509\u050A\x05\xE7r\x02\u050A\u050B\x05\xE5q\x02\u050B\xB4" + + "\x03\x02\x02\x02\u050C\u050D\x05\xF7z\x02\u050D\u050E\x05\xDBl\x02\u050E" + + "\u050F\x05\xF1w\x02\u050F\u0510\x05\xD9k\x02\u0510\xB6\x03\x02\x02\x02" + + "\u0511\u0512\x07~\x02\x02\u0512\u0513\x03\x02\x02\x02\u0513\u0514\bZ\t" + + "\x02\u0514\u0515\bZ\n\x02\u0515\xB8\x03\x02\x02\x02\u0516\u0517\x07_\x02" + + "\x02\u0517\u0518\x03\x02\x02\x02\u0518\u0519\b[\n\x02\u0519\u051A\b[\n" + + "\x02\u051A\u051B\b[\v\x02\u051B\xBA\x03\x02\x02\x02\u051C\u051D\x07.\x02" + + "\x02\u051D\u051E\x03\x02\x02\x02\u051E\u051F\b\\\f\x02\u051F\xBC\x03\x02" + + "\x02\x02\u0520\u0521\x07?\x02\x02\u0521\u0522\x03\x02\x02\x02\u0522\u0523" + + "\b]\r\x02\u0523\xBE\x03\x02\x02\x02\u0524\u0526\x05\xC1_\x02\u0525\u0524" + + "\x03\x02\x02\x02\u0526\u0527\x03\x02\x02\x02\u0527\u0525\x03\x02\x02\x02" + + "\u0527\u0528\x03\x02\x02\x02\u0528\xC0\x03\x02\x02\x02\u0529\u052B\n\f" + + "\x02\x02\u052A\u0529\x03\x02\x02\x02\u052B\u052C\x03\x02\x02\x02\u052C" + + "\u052A\x03\x02\x02\x02\u052C\u052D\x03\x02\x02\x02\u052D\u0531\x03\x02" + + "\x02\x02\u052E\u052F\x071\x02\x02\u052F\u0531\n\r\x02\x02\u0530\u052A" + + "\x03\x02\x02\x02\u0530\u052E\x03\x02\x02\x02\u0531\xC2\x03\x02\x02\x02" + + "\u0532\u0533\x05\x93H\x02\u0533\xC4\x03\x02\x02\x02\u0534\u0535\x05)\x13" + + "\x02\u0535\u0536\x03\x02\x02\x02\u0536\u0537\ba\x06\x02\u0537\xC6\x03" + + "\x02\x02\x02\u0538\u0539\x05+\x14\x02\u0539\u053A\x03\x02\x02\x02\u053A" + + "\u053B\bb\x06\x02\u053B\xC8\x03\x02\x02\x02\u053C\u053D\x05-\x15\x02\u053D" + + "\u053E\x03\x02\x02\x02\u053E\u053F\bc\x06\x02\u053F\xCA\x03\x02\x02\x02" + + "\u0540\u0541\t\x0E\x02\x02\u0541\xCC\x03\x02\x02\x02\u0542\u0543\t\x0F" + + "\x02\x02\u0543\xCE\x03\x02\x02\x02\u0544\u0545\t\x10\x02\x02\u0545\xD0" + + "\x03\x02\x02\x02\u0546\u0547\t\x11\x02\x02\u0547\xD2\x03\x02\x02\x02\u0548" + + "\u0549\t\b\x02\x02\u0549\xD4\x03\x02\x02\x02\u054A\u054B\t\x12\x02\x02" + + "\u054B\xD6\x03\x02\x02\x02\u054C\u054D\t\x13\x02\x02\u054D\xD8\x03\x02" + + "\x02\x02\u054E\u054F\t\x14\x02\x02\u054F\xDA\x03\x02\x02\x02\u0550\u0551" + + "\t\x15\x02\x02\u0551\xDC\x03\x02\x02\x02\u0552\u0553\t\x16\x02\x02\u0553" + + "\xDE\x03\x02\x02\x02\u0554\u0555\t\x17\x02\x02\u0555\xE0\x03\x02\x02\x02" + + "\u0556\u0557\t\x18\x02\x02\u0557\xE2\x03\x02\x02\x02\u0558\u0559\t\x19" + + "\x02\x02\u0559\xE4\x03\x02\x02\x02\u055A\u055B\t\x1A\x02\x02\u055B\xE6" + + "\x03\x02\x02\x02\u055C\u055D\t\x1B\x02\x02\u055D\xE8\x03\x02\x02\x02\u055E" + + "\u055F\t\x1C\x02\x02\u055F\xEA\x03\x02\x02\x02\u0560\u0561\t\x1D\x02\x02" + + "\u0561\xEC\x03\x02\x02\x02\u0562\u0563\t\x1E\x02\x02\u0563\xEE\x03\x02" + + "\x02\x02\u0564\u0565\t\x1F\x02\x02\u0565\xF0\x03\x02\x02\x02\u0566\u0567" + + "\t \x02\x02\u0567\xF2\x03\x02\x02\x02\u0568\u0569\t!\x02\x02\u0569\xF4" + + "\x03\x02\x02\x02\u056A\u056B\t\"\x02\x02\u056B\xF6\x03\x02\x02\x02\u056C" + + "\u056D\t#\x02\x02\u056D\xF8\x03\x02\x02\x02\u056E\u056F\t$\x02\x02\u056F" + + "\xFA\x03\x02\x02\x02\u0570\u0571\t%\x02\x02\u0571\xFC\x03\x02\x02\x02" + + "\u0572\u0573\t&\x02\x02\u0573\xFE\x03\x02\x02\x022\x02\x03\x04\x05\x06" + + "\u0190\u0194\u0197\u01A0\u01A2\u01AD\u01D6\u01DB\u01E0\u01E2\u01ED\u01F5" + + "\u01F8\u01FA\u01FF\u0204\u020A\u0211\u0216\u021C\u021F\u0227\u022B\u024C" + + "\u02A0\u02AC\u02C2\u02D3\u043F\u0492\u04A4\u04A6\u04AE\u04B0\u04B2\u04B8" + + "\u04BA\u04F0\u04F5\u04F9\u0527\u052C\u0530\x0E\x07\x04\x02\x07\x03\x02" + + "\x07\x05\x02\x07\x06\x02\x02\x03\x02\t%\x02\x07\x02\x02\t\x1A\x02\x06" + + "\x02\x02\t&\x02\t\"\x02\t!\x02"; + public static readonly _serializedATN: string = Utils.join( + [ + esql_lexer._serializedATNSegment0, + esql_lexer._serializedATNSegment1, + esql_lexer._serializedATNSegment2, + ], + "", + ); public static __ATN: ATN; public static get _ATN(): ATN { if (!esql_lexer.__ATN) { diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 b/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 index 6196874af91bd..b062dc4f140e7 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 @@ -23,19 +23,50 @@ sourceCommand : explainCommand | fromCommand | rowCommand + | showCommand ; processingCommand : evalCommand | limitCommand | projectCommand + | keepCommand + | renameCommand + | dropCommand + | dissectCommand + | grokCommand | sortCommand | statsCommand | whereCommand + | mvExpandCommand + | enrichCommand + ; + +enrichCommand + : ENRICH policyName=enrichIdentifier (ON matchField=enrichFieldIdentifier)? (WITH enrichWithClause (COMMA enrichWithClause)*)? + ; + +enrichWithClause + : (newName=enrichFieldIdentifier ASSIGN)? enrichField=enrichFieldIdentifier + ; + +mvExpandCommand + : MV_EXPAND qualifiedNames ; whereCommand - : WHERE booleanExpression + : WHERE whereBooleanExpression + ; + +whereBooleanExpression + : NOT whereBooleanExpression + | valueExpression + | regexBooleanExpression + | left=whereBooleanExpression operator=AND right=whereBooleanExpression + | left=whereBooleanExpression operator=OR right=whereBooleanExpression + | valueExpression (NOT)? IN LP valueExpression (COMMA valueExpression)* RP + | (NOT)? WHERE_FUNCTIONS LP qualifiedName ((COMMA functionExpressionArgument)*)? RP + | valueExpression IS NOT? NULL ; booleanExpression @@ -45,6 +76,11 @@ booleanExpression | left=booleanExpression operator=OR right=booleanExpression ; +regexBooleanExpression + : valueExpression (NOT)? kind=LIKE pattern=string + | valueExpression (NOT)? kind=RLIKE pattern=string + ; + valueExpression : operatorExpression | comparison @@ -58,9 +94,14 @@ mathFn : functionIdentifier LP (functionExpressionArgument (COMMA functionExpressionArgument)*)? RP ; +mathEvalFn + : mathFunctionIdentifier LP (mathFunctionExpressionArgument (COMMA mathFunctionExpressionArgument)*)? RP + ; + operatorExpression : primaryExpression | mathFn + | mathEvalFn | operator=(MINUS | PLUS) operatorExpression | left=operatorExpression operator=(ASTERISK | SLASH | PERCENT) right=operatorExpression | left=operatorExpression operator=(PLUS | MINUS) right=operatorExpression @@ -86,12 +127,21 @@ field | userVariable ASSIGN booleanExpression ; +enrichFieldIdentifier + : ENR_UNQUOTED_IDENTIFIER + | ENR_QUOTED_IDENTIFIER + ; + userVariable : identifier ; fromCommand - : FROM sourceIdentifier (COMMA sourceIdentifier)* + : FROM sourceIdentifier (COMMA sourceIdentifier)* metadata? + ; + +metadata + : OPENING_BRACKET METADATA sourceIdentifier (COMMA sourceIdentifier)* CLOSING_BRACKET ; evalCommand @@ -99,7 +149,7 @@ evalCommand ; statsCommand - : STATS fields (BY qualifiedNames)? + : STATS fields? (BY qualifiedNames)? ; sourceIdentifier @@ -107,9 +157,24 @@ sourceIdentifier | SRC_QUOTED_IDENTIFIER ; +enrichIdentifier + : ENR_UNQUOTED_IDENTIFIER + | ENR_QUOTED_IDENTIFIER + ; + functionExpressionArgument : qualifiedName | string + | number + ; + +mathFunctionExpressionArgument + : qualifiedName + | string + | number + | operatorExpression + | number (DATE_LITERAL) + | comparison ; qualifiedName @@ -123,6 +188,11 @@ qualifiedNames identifier : UNQUOTED_IDENTIFIER | QUOTED_IDENTIFIER + | ASTERISK + ; + +mathFunctionIdentifier + : MATH_FUNCTION ; functionIdentifier @@ -130,10 +200,18 @@ functionIdentifier ; constant - : NULL #nullLiteral - | number #numericLiteral - | booleanValue #booleanLiteral - | string #stringLiteral + : NULL + | numericValue + | booleanValue + | string + | OPENING_BRACKET numericValue (COMMA numericValue)* CLOSING_BRACKET + | OPENING_BRACKET booleanValue (COMMA booleanValue)* CLOSING_BRACKET + | OPENING_BRACKET string (COMMA string)* CLOSING_BRACKET + ; + +numericValue + : decimalValue + | integerValue ; limitCommand @@ -149,12 +227,44 @@ orderExpression ; projectCommand - : PROJECT projectClause (COMMA projectClause)* + : PROJECT qualifiedNames + ; + +keepCommand + : KEEP qualifiedNames + ; + + +dropCommand + : DROP qualifiedNames + ; + +renameVariable + : identifier (DOT identifier)* + ; + +renameCommand + : RENAME renameClause (COMMA renameClause)* + ; + +renameClause + : qualifiedName AS renameVariable ; -projectClause - : sourceIdentifier - | newName=sourceIdentifier ASSIGN oldName=sourceIdentifier +dissectCommand + : DISSECT qualifiedNames string commandOptions? + ; + +grokCommand + : GROK qualifiedNames string + ; + +commandOptions + : commandOption (COMMA commandOption)* + ; + +commandOption + : identifier ASSIGN constant ; booleanValue @@ -166,6 +276,14 @@ number | INTEGER_LITERAL #integerLiteral ; +decimalValue + : DECIMAL_LITERAL + ; + +integerValue + : INTEGER_LITERAL + ; + string : STRING ; @@ -181,3 +299,8 @@ explainCommand subqueryExpression : OPENING_BRACKET query CLOSING_BRACKET ; + +showCommand + : SHOW INFO + | SHOW FUNCTIONS + ; diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.interp b/packages/kbn-monaco/src/esql/antlr/esql_parser.interp index 39dc1a09fb8ba..8c0671e0d0a59 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.interp +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.interp @@ -1,14 +1,25 @@ token literal names: null -'eval' -'explain' -'from' -'row' -'stats' -'where' -'sort' -'limit' -'project' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null null null null @@ -17,17 +28,26 @@ null null null 'by' +null 'and' null null '.' '(' -'[' +null ']' -'not' -'null' +null +null +null +null +null +null +null 'or' ')' +'_' +'info' +'functions' null null '+' @@ -35,6 +55,7 @@ null '*' '/' '%' +'10' null 'nulls' null @@ -49,9 +70,22 @@ null null null null +null +null +null +null +null +null +null +null +null +null +null token symbolic names: null +DISSECT +GROK EVAL EXPLAIN FROM @@ -59,16 +93,26 @@ ROW STATS WHERE SORT +MV_EXPAND LIMIT PROJECT +DROP +RENAME +SHOW +ENRICH +KEEP LINE_COMMENT MULTILINE_COMMENT WS +EXPLAIN_WS +EXPLAIN_LINE_COMMENT +EXPLAIN_MULTILINE_COMMENT PIPE STRING INTEGER_LITERAL DECIMAL_LITERAL BY +DATE_LITERAL AND ASSIGN COMMA @@ -77,9 +121,17 @@ LP OPENING_BRACKET CLOSING_BRACKET NOT +LIKE +RLIKE +IN +IS +AS NULL OR RP +UNDERSCORE +INFO +FUNCTIONS BOOLEAN_VALUE COMPARISON_OPERATOR PLUS @@ -87,59 +139,94 @@ MINUS ASTERISK SLASH PERCENT +TEN ORDERING NULLS_ORDERING NULLS_ORDERING_DIRECTION +MATH_FUNCTION UNARY_FUNCTION +WHERE_FUNCTIONS UNQUOTED_IDENTIFIER QUOTED_IDENTIFIER EXPR_LINE_COMMENT EXPR_MULTILINE_COMMENT EXPR_WS +METADATA SRC_UNQUOTED_IDENTIFIER SRC_QUOTED_IDENTIFIER SRC_LINE_COMMENT SRC_MULTILINE_COMMENT SRC_WS +ON +WITH +ENR_UNQUOTED_IDENTIFIER +ENR_QUOTED_IDENTIFIER +ENR_LINE_COMMENT +ENR_MULTILINE_COMMENT +ENR_WS +EXPLAIN_PIPE rule names: singleStatement query sourceCommand processingCommand +enrichCommand +enrichWithClause +mvExpandCommand whereCommand +whereBooleanExpression booleanExpression +regexBooleanExpression valueExpression comparison mathFn +mathEvalFn operatorExpression primaryExpression rowCommand fields field +enrichFieldIdentifier userVariable fromCommand +metadata evalCommand statsCommand sourceIdentifier +enrichIdentifier functionExpressionArgument +mathFunctionExpressionArgument qualifiedName qualifiedNames identifier +mathFunctionIdentifier functionIdentifier constant +numericValue limitCommand sortCommand orderExpression projectCommand -projectClause +keepCommand +dropCommand +renameVariable +renameCommand +renameClause +dissectCommand +grokCommand +commandOptions +commandOption booleanValue number +decimalValue +integerValue string comparisonOperator explainCommand subqueryExpression +showCommand atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 51, 307, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 84, 10, 3, 12, 3, 14, 3, 87, 11, 3, 3, 4, 3, 4, 3, 4, 5, 4, 92, 10, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 100, 10, 5, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 109, 10, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 7, 7, 117, 10, 7, 12, 7, 14, 7, 120, 11, 7, 3, 8, 3, 8, 5, 8, 124, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 135, 10, 10, 12, 10, 14, 10, 138, 11, 10, 5, 10, 140, 10, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 5, 11, 149, 10, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 7, 11, 157, 10, 11, 12, 11, 14, 11, 160, 11, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 7, 12, 173, 10, 12, 12, 12, 14, 12, 176, 11, 12, 5, 12, 178, 10, 12, 3, 12, 3, 12, 5, 12, 182, 10, 12, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 7, 14, 190, 10, 14, 12, 14, 14, 14, 193, 11, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 5, 15, 200, 10, 15, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 208, 10, 17, 12, 17, 14, 17, 211, 11, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 5, 19, 220, 10, 19, 3, 20, 3, 20, 3, 21, 3, 21, 5, 21, 226, 10, 21, 3, 22, 3, 22, 3, 22, 7, 22, 231, 10, 22, 12, 22, 14, 22, 234, 11, 22, 3, 23, 3, 23, 3, 23, 7, 23, 239, 10, 23, 12, 23, 14, 23, 242, 11, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 5, 26, 252, 10, 26, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 261, 10, 28, 12, 28, 14, 28, 264, 11, 28, 3, 29, 3, 29, 5, 29, 268, 10, 29, 3, 29, 3, 29, 5, 29, 272, 10, 29, 3, 30, 3, 30, 3, 30, 3, 30, 7, 30, 278, 10, 30, 12, 30, 14, 30, 281, 11, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 5, 31, 288, 10, 31, 3, 32, 3, 32, 3, 33, 3, 33, 5, 33, 294, 10, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 2, 2, 5, 4, 12, 20, 38, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 2, 6, 3, 2, 33, 34, 3, 2, 35, 37, 3, 2, 47, 48, 3, 2, 42, 43, 2, 309, 2, 74, 3, 2, 2, 2, 4, 77, 3, 2, 2, 2, 6, 91, 3, 2, 2, 2, 8, 99, 3, 2, 2, 2, 10, 101, 3, 2, 2, 2, 12, 108, 3, 2, 2, 2, 14, 123, 3, 2, 2, 2, 16, 125, 3, 2, 2, 2, 18, 129, 3, 2, 2, 2, 20, 148, 3, 2, 2, 2, 22, 181, 3, 2, 2, 2, 24, 183, 3, 2, 2, 2, 26, 186, 3, 2, 2, 2, 28, 199, 3, 2, 2, 2, 30, 201, 3, 2, 2, 2, 32, 203, 3, 2, 2, 2, 34, 212, 3, 2, 2, 2, 36, 215, 3, 2, 2, 2, 38, 221, 3, 2, 2, 2, 40, 225, 3, 2, 2, 2, 42, 227, 3, 2, 2, 2, 44, 235, 3, 2, 2, 2, 46, 243, 3, 2, 2, 2, 48, 245, 3, 2, 2, 2, 50, 251, 3, 2, 2, 2, 52, 253, 3, 2, 2, 2, 54, 256, 3, 2, 2, 2, 56, 265, 3, 2, 2, 2, 58, 273, 3, 2, 2, 2, 60, 287, 3, 2, 2, 2, 62, 289, 3, 2, 2, 2, 64, 293, 3, 2, 2, 2, 66, 295, 3, 2, 2, 2, 68, 297, 3, 2, 2, 2, 70, 299, 3, 2, 2, 2, 72, 302, 3, 2, 2, 2, 74, 75, 5, 4, 3, 2, 75, 76, 7, 2, 2, 3, 76, 3, 3, 2, 2, 2, 77, 78, 8, 3, 1, 2, 78, 79, 5, 6, 4, 2, 79, 85, 3, 2, 2, 2, 80, 81, 12, 3, 2, 2, 81, 82, 7, 15, 2, 2, 82, 84, 5, 8, 5, 2, 83, 80, 3, 2, 2, 2, 84, 87, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 85, 86, 3, 2, 2, 2, 86, 5, 3, 2, 2, 2, 87, 85, 3, 2, 2, 2, 88, 92, 5, 70, 36, 2, 89, 92, 5, 32, 17, 2, 90, 92, 5, 24, 13, 2, 91, 88, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 91, 90, 3, 2, 2, 2, 92, 7, 3, 2, 2, 2, 93, 100, 5, 34, 18, 2, 94, 100, 5, 52, 27, 2, 95, 100, 5, 58, 30, 2, 96, 100, 5, 54, 28, 2, 97, 100, 5, 36, 19, 2, 98, 100, 5, 10, 6, 2, 99, 93, 3, 2, 2, 2, 99, 94, 3, 2, 2, 2, 99, 95, 3, 2, 2, 2, 99, 96, 3, 2, 2, 2, 99, 97, 3, 2, 2, 2, 99, 98, 3, 2, 2, 2, 100, 9, 3, 2, 2, 2, 101, 102, 7, 8, 2, 2, 102, 103, 5, 12, 7, 2, 103, 11, 3, 2, 2, 2, 104, 105, 8, 7, 1, 2, 105, 106, 7, 27, 2, 2, 106, 109, 5, 12, 7, 6, 107, 109, 5, 14, 8, 2, 108, 104, 3, 2, 2, 2, 108, 107, 3, 2, 2, 2, 109, 118, 3, 2, 2, 2, 110, 111, 12, 4, 2, 2, 111, 112, 7, 20, 2, 2, 112, 117, 5, 12, 7, 5, 113, 114, 12, 3, 2, 2, 114, 115, 7, 29, 2, 2, 115, 117, 5, 12, 7, 4, 116, 110, 3, 2, 2, 2, 116, 113, 3, 2, 2, 2, 117, 120, 3, 2, 2, 2, 118, 116, 3, 2, 2, 2, 118, 119, 3, 2, 2, 2, 119, 13, 3, 2, 2, 2, 120, 118, 3, 2, 2, 2, 121, 124, 5, 20, 11, 2, 122, 124, 5, 16, 9, 2, 123, 121, 3, 2, 2, 2, 123, 122, 3, 2, 2, 2, 124, 15, 3, 2, 2, 2, 125, 126, 5, 20, 11, 2, 126, 127, 5, 68, 35, 2, 127, 128, 5, 20, 11, 2, 128, 17, 3, 2, 2, 2, 129, 130, 5, 48, 25, 2, 130, 139, 7, 24, 2, 2, 131, 136, 5, 40, 21, 2, 132, 133, 7, 22, 2, 2, 133, 135, 5, 40, 21, 2, 134, 132, 3, 2, 2, 2, 135, 138, 3, 2, 2, 2, 136, 134, 3, 2, 2, 2, 136, 137, 3, 2, 2, 2, 137, 140, 3, 2, 2, 2, 138, 136, 3, 2, 2, 2, 139, 131, 3, 2, 2, 2, 139, 140, 3, 2, 2, 2, 140, 141, 3, 2, 2, 2, 141, 142, 7, 30, 2, 2, 142, 19, 3, 2, 2, 2, 143, 144, 8, 11, 1, 2, 144, 149, 5, 22, 12, 2, 145, 149, 5, 18, 10, 2, 146, 147, 9, 2, 2, 2, 147, 149, 5, 20, 11, 5, 148, 143, 3, 2, 2, 2, 148, 145, 3, 2, 2, 2, 148, 146, 3, 2, 2, 2, 149, 158, 3, 2, 2, 2, 150, 151, 12, 4, 2, 2, 151, 152, 9, 3, 2, 2, 152, 157, 5, 20, 11, 5, 153, 154, 12, 3, 2, 2, 154, 155, 9, 2, 2, 2, 155, 157, 5, 20, 11, 4, 156, 150, 3, 2, 2, 2, 156, 153, 3, 2, 2, 2, 157, 160, 3, 2, 2, 2, 158, 156, 3, 2, 2, 2, 158, 159, 3, 2, 2, 2, 159, 21, 3, 2, 2, 2, 160, 158, 3, 2, 2, 2, 161, 182, 5, 50, 26, 2, 162, 182, 5, 42, 22, 2, 163, 164, 7, 24, 2, 2, 164, 165, 5, 12, 7, 2, 165, 166, 7, 30, 2, 2, 166, 182, 3, 2, 2, 2, 167, 168, 5, 46, 24, 2, 168, 177, 7, 24, 2, 2, 169, 174, 5, 12, 7, 2, 170, 171, 7, 22, 2, 2, 171, 173, 5, 12, 7, 2, 172, 170, 3, 2, 2, 2, 173, 176, 3, 2, 2, 2, 174, 172, 3, 2, 2, 2, 174, 175, 3, 2, 2, 2, 175, 178, 3, 2, 2, 2, 176, 174, 3, 2, 2, 2, 177, 169, 3, 2, 2, 2, 177, 178, 3, 2, 2, 2, 178, 179, 3, 2, 2, 2, 179, 180, 7, 30, 2, 2, 180, 182, 3, 2, 2, 2, 181, 161, 3, 2, 2, 2, 181, 162, 3, 2, 2, 2, 181, 163, 3, 2, 2, 2, 181, 167, 3, 2, 2, 2, 182, 23, 3, 2, 2, 2, 183, 184, 7, 6, 2, 2, 184, 185, 5, 26, 14, 2, 185, 25, 3, 2, 2, 2, 186, 191, 5, 28, 15, 2, 187, 188, 7, 22, 2, 2, 188, 190, 5, 28, 15, 2, 189, 187, 3, 2, 2, 2, 190, 193, 3, 2, 2, 2, 191, 189, 3, 2, 2, 2, 191, 192, 3, 2, 2, 2, 192, 27, 3, 2, 2, 2, 193, 191, 3, 2, 2, 2, 194, 200, 5, 12, 7, 2, 195, 196, 5, 30, 16, 2, 196, 197, 7, 21, 2, 2, 197, 198, 5, 12, 7, 2, 198, 200, 3, 2, 2, 2, 199, 194, 3, 2, 2, 2, 199, 195, 3, 2, 2, 2, 200, 29, 3, 2, 2, 2, 201, 202, 5, 46, 24, 2, 202, 31, 3, 2, 2, 2, 203, 204, 7, 5, 2, 2, 204, 209, 5, 38, 20, 2, 205, 206, 7, 22, 2, 2, 206, 208, 5, 38, 20, 2, 207, 205, 3, 2, 2, 2, 208, 211, 3, 2, 2, 2, 209, 207, 3, 2, 2, 2, 209, 210, 3, 2, 2, 2, 210, 33, 3, 2, 2, 2, 211, 209, 3, 2, 2, 2, 212, 213, 7, 3, 2, 2, 213, 214, 5, 26, 14, 2, 214, 35, 3, 2, 2, 2, 215, 216, 7, 7, 2, 2, 216, 219, 5, 26, 14, 2, 217, 218, 7, 19, 2, 2, 218, 220, 5, 44, 23, 2, 219, 217, 3, 2, 2, 2, 219, 220, 3, 2, 2, 2, 220, 37, 3, 2, 2, 2, 221, 222, 9, 4, 2, 2, 222, 39, 3, 2, 2, 2, 223, 226, 5, 42, 22, 2, 224, 226, 5, 66, 34, 2, 225, 223, 3, 2, 2, 2, 225, 224, 3, 2, 2, 2, 226, 41, 3, 2, 2, 2, 227, 232, 5, 46, 24, 2, 228, 229, 7, 23, 2, 2, 229, 231, 5, 46, 24, 2, 230, 228, 3, 2, 2, 2, 231, 234, 3, 2, 2, 2, 232, 230, 3, 2, 2, 2, 232, 233, 3, 2, 2, 2, 233, 43, 3, 2, 2, 2, 234, 232, 3, 2, 2, 2, 235, 240, 5, 42, 22, 2, 236, 237, 7, 22, 2, 2, 237, 239, 5, 42, 22, 2, 238, 236, 3, 2, 2, 2, 239, 242, 3, 2, 2, 2, 240, 238, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 45, 3, 2, 2, 2, 242, 240, 3, 2, 2, 2, 243, 244, 9, 5, 2, 2, 244, 47, 3, 2, 2, 2, 245, 246, 7, 41, 2, 2, 246, 49, 3, 2, 2, 2, 247, 252, 7, 28, 2, 2, 248, 252, 5, 64, 33, 2, 249, 252, 5, 62, 32, 2, 250, 252, 5, 66, 34, 2, 251, 247, 3, 2, 2, 2, 251, 248, 3, 2, 2, 2, 251, 249, 3, 2, 2, 2, 251, 250, 3, 2, 2, 2, 252, 51, 3, 2, 2, 2, 253, 254, 7, 10, 2, 2, 254, 255, 7, 17, 2, 2, 255, 53, 3, 2, 2, 2, 256, 257, 7, 9, 2, 2, 257, 262, 5, 56, 29, 2, 258, 259, 7, 22, 2, 2, 259, 261, 5, 56, 29, 2, 260, 258, 3, 2, 2, 2, 261, 264, 3, 2, 2, 2, 262, 260, 3, 2, 2, 2, 262, 263, 3, 2, 2, 2, 263, 55, 3, 2, 2, 2, 264, 262, 3, 2, 2, 2, 265, 267, 5, 12, 7, 2, 266, 268, 7, 38, 2, 2, 267, 266, 3, 2, 2, 2, 267, 268, 3, 2, 2, 2, 268, 271, 3, 2, 2, 2, 269, 270, 7, 39, 2, 2, 270, 272, 7, 40, 2, 2, 271, 269, 3, 2, 2, 2, 271, 272, 3, 2, 2, 2, 272, 57, 3, 2, 2, 2, 273, 274, 7, 11, 2, 2, 274, 279, 5, 60, 31, 2, 275, 276, 7, 22, 2, 2, 276, 278, 5, 60, 31, 2, 277, 275, 3, 2, 2, 2, 278, 281, 3, 2, 2, 2, 279, 277, 3, 2, 2, 2, 279, 280, 3, 2, 2, 2, 280, 59, 3, 2, 2, 2, 281, 279, 3, 2, 2, 2, 282, 288, 5, 38, 20, 2, 283, 284, 5, 38, 20, 2, 284, 285, 7, 21, 2, 2, 285, 286, 5, 38, 20, 2, 286, 288, 3, 2, 2, 2, 287, 282, 3, 2, 2, 2, 287, 283, 3, 2, 2, 2, 288, 61, 3, 2, 2, 2, 289, 290, 7, 31, 2, 2, 290, 63, 3, 2, 2, 2, 291, 294, 7, 18, 2, 2, 292, 294, 7, 17, 2, 2, 293, 291, 3, 2, 2, 2, 293, 292, 3, 2, 2, 2, 294, 65, 3, 2, 2, 2, 295, 296, 7, 16, 2, 2, 296, 67, 3, 2, 2, 2, 297, 298, 7, 32, 2, 2, 298, 69, 3, 2, 2, 2, 299, 300, 7, 4, 2, 2, 300, 301, 5, 72, 37, 2, 301, 71, 3, 2, 2, 2, 302, 303, 7, 25, 2, 2, 303, 304, 5, 4, 3, 2, 304, 305, 7, 26, 2, 2, 305, 73, 3, 2, 2, 2, 31, 85, 91, 99, 108, 116, 118, 123, 136, 139, 148, 156, 158, 174, 177, 181, 191, 199, 209, 219, 225, 232, 240, 251, 262, 267, 271, 279, 287, 293] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 83, 594, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 130, 10, 3, 12, 3, 14, 3, 133, 11, 3, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 139, 10, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 154, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 160, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 166, 10, 6, 12, 6, 14, 6, 169, 11, 6, 5, 6, 171, 10, 6, 3, 7, 3, 7, 3, 7, 5, 7, 176, 10, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 193, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 200, 10, 10, 12, 10, 14, 10, 203, 11, 10, 3, 10, 3, 10, 3, 10, 5, 10, 208, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 215, 10, 10, 12, 10, 14, 10, 218, 11, 10, 5, 10, 220, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 227, 10, 10, 3, 10, 3, 10, 5, 10, 231, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 239, 10, 10, 12, 10, 14, 10, 242, 11, 10, 3, 11, 3, 11, 3, 11, 3, 11, 5, 11, 248, 10, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 7, 11, 256, 10, 11, 12, 11, 14, 11, 259, 11, 11, 3, 12, 3, 12, 5, 12, 263, 10, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 5, 12, 270, 10, 12, 3, 12, 3, 12, 3, 12, 5, 12, 275, 10, 12, 3, 13, 3, 13, 5, 13, 279, 10, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 7, 15, 290, 10, 15, 12, 15, 14, 15, 293, 11, 15, 5, 15, 295, 10, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 7, 16, 304, 10, 16, 12, 16, 14, 16, 307, 11, 16, 5, 16, 309, 10, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 5, 17, 319, 10, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 327, 10, 17, 12, 17, 14, 17, 330, 11, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 343, 10, 18, 12, 18, 14, 18, 346, 11, 18, 5, 18, 348, 10, 18, 3, 18, 3, 18, 5, 18, 352, 10, 18, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 7, 20, 360, 10, 20, 12, 20, 14, 20, 363, 11, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 370, 10, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 7, 24, 380, 10, 24, 12, 24, 14, 24, 383, 11, 24, 3, 24, 5, 24, 386, 10, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 7, 25, 393, 10, 25, 12, 25, 14, 25, 396, 11, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 5, 27, 405, 10, 27, 3, 27, 3, 27, 5, 27, 409, 10, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 5, 30, 418, 10, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 5, 31, 428, 10, 31, 3, 32, 3, 32, 3, 32, 7, 32, 433, 10, 32, 12, 32, 14, 32, 436, 11, 32, 3, 33, 3, 33, 3, 33, 7, 33, 441, 10, 33, 12, 33, 14, 33, 444, 11, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 7, 37, 460, 10, 37, 12, 37, 14, 37, 463, 11, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 7, 37, 471, 10, 37, 12, 37, 14, 37, 474, 11, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 7, 37, 482, 10, 37, 12, 37, 14, 37, 485, 11, 37, 3, 37, 3, 37, 5, 37, 489, 10, 37, 3, 38, 3, 38, 5, 38, 493, 10, 38, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 7, 40, 502, 10, 40, 12, 40, 14, 40, 505, 11, 40, 3, 41, 3, 41, 5, 41, 509, 10, 41, 3, 41, 3, 41, 5, 41, 513, 10, 41, 3, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 7, 45, 527, 10, 45, 12, 45, 14, 45, 530, 11, 45, 3, 46, 3, 46, 3, 46, 3, 46, 7, 46, 536, 10, 46, 12, 46, 14, 46, 539, 11, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 48, 5, 48, 549, 10, 48, 3, 49, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 7, 50, 558, 10, 50, 12, 50, 14, 50, 561, 11, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 53, 3, 53, 5, 53, 571, 10, 53, 3, 54, 3, 54, 3, 55, 3, 55, 3, 56, 3, 56, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 5, 60, 592, 10, 60, 3, 60, 2, 2, 6, 4, 18, 20, 32, 61, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 78, 2, 80, 2, 82, 2, 84, 2, 86, 2, 88, 2, 90, 2, 92, 2, 94, 2, 96, 2, 98, 2, 100, 2, 102, 2, 104, 2, 106, 2, 108, 2, 110, 2, 112, 2, 114, 2, 116, 2, 118, 2, 2, 7, 3, 2, 53, 54, 3, 2, 55, 57, 3, 2, 78, 79, 3, 2, 71, 72, 4, 2, 55, 55, 65, 66, 2, 623, 2, 120, 3, 2, 2, 2, 4, 123, 3, 2, 2, 2, 6, 138, 3, 2, 2, 2, 8, 153, 3, 2, 2, 2, 10, 155, 3, 2, 2, 2, 12, 175, 3, 2, 2, 2, 14, 179, 3, 2, 2, 2, 16, 182, 3, 2, 2, 2, 18, 230, 3, 2, 2, 2, 20, 247, 3, 2, 2, 2, 22, 274, 3, 2, 2, 2, 24, 278, 3, 2, 2, 2, 26, 280, 3, 2, 2, 2, 28, 284, 3, 2, 2, 2, 30, 298, 3, 2, 2, 2, 32, 318, 3, 2, 2, 2, 34, 351, 3, 2, 2, 2, 36, 353, 3, 2, 2, 2, 38, 356, 3, 2, 2, 2, 40, 369, 3, 2, 2, 2, 42, 371, 3, 2, 2, 2, 44, 373, 3, 2, 2, 2, 46, 375, 3, 2, 2, 2, 48, 387, 3, 2, 2, 2, 50, 399, 3, 2, 2, 2, 52, 402, 3, 2, 2, 2, 54, 410, 3, 2, 2, 2, 56, 412, 3, 2, 2, 2, 58, 417, 3, 2, 2, 2, 60, 427, 3, 2, 2, 2, 62, 429, 3, 2, 2, 2, 64, 437, 3, 2, 2, 2, 66, 445, 3, 2, 2, 2, 68, 447, 3, 2, 2, 2, 70, 449, 3, 2, 2, 2, 72, 488, 3, 2, 2, 2, 74, 492, 3, 2, 2, 2, 76, 494, 3, 2, 2, 2, 78, 497, 3, 2, 2, 2, 80, 506, 3, 2, 2, 2, 82, 514, 3, 2, 2, 2, 84, 517, 3, 2, 2, 2, 86, 520, 3, 2, 2, 2, 88, 523, 3, 2, 2, 2, 90, 531, 3, 2, 2, 2, 92, 540, 3, 2, 2, 2, 94, 544, 3, 2, 2, 2, 96, 550, 3, 2, 2, 2, 98, 554, 3, 2, 2, 2, 100, 562, 3, 2, 2, 2, 102, 566, 3, 2, 2, 2, 104, 570, 3, 2, 2, 2, 106, 572, 3, 2, 2, 2, 108, 574, 3, 2, 2, 2, 110, 576, 3, 2, 2, 2, 112, 578, 3, 2, 2, 2, 114, 580, 3, 2, 2, 2, 116, 583, 3, 2, 2, 2, 118, 591, 3, 2, 2, 2, 120, 121, 5, 4, 3, 2, 121, 122, 7, 2, 2, 3, 122, 3, 3, 2, 2, 2, 123, 124, 8, 3, 1, 2, 124, 125, 5, 6, 4, 2, 125, 131, 3, 2, 2, 2, 126, 127, 12, 3, 2, 2, 127, 128, 7, 26, 2, 2, 128, 130, 5, 8, 5, 2, 129, 126, 3, 2, 2, 2, 130, 133, 3, 2, 2, 2, 131, 129, 3, 2, 2, 2, 131, 132, 3, 2, 2, 2, 132, 5, 3, 2, 2, 2, 133, 131, 3, 2, 2, 2, 134, 139, 5, 114, 58, 2, 135, 139, 5, 46, 24, 2, 136, 139, 5, 36, 19, 2, 137, 139, 5, 118, 60, 2, 138, 134, 3, 2, 2, 2, 138, 135, 3, 2, 2, 2, 138, 136, 3, 2, 2, 2, 138, 137, 3, 2, 2, 2, 139, 7, 3, 2, 2, 2, 140, 154, 5, 50, 26, 2, 141, 154, 5, 76, 39, 2, 142, 154, 5, 82, 42, 2, 143, 154, 5, 84, 43, 2, 144, 154, 5, 90, 46, 2, 145, 154, 5, 86, 44, 2, 146, 154, 5, 94, 48, 2, 147, 154, 5, 96, 49, 2, 148, 154, 5, 78, 40, 2, 149, 154, 5, 52, 27, 2, 150, 154, 5, 16, 9, 2, 151, 154, 5, 14, 8, 2, 152, 154, 5, 10, 6, 2, 153, 140, 3, 2, 2, 2, 153, 141, 3, 2, 2, 2, 153, 142, 3, 2, 2, 2, 153, 143, 3, 2, 2, 2, 153, 144, 3, 2, 2, 2, 153, 145, 3, 2, 2, 2, 153, 146, 3, 2, 2, 2, 153, 147, 3, 2, 2, 2, 153, 148, 3, 2, 2, 2, 153, 149, 3, 2, 2, 2, 153, 150, 3, 2, 2, 2, 153, 151, 3, 2, 2, 2, 153, 152, 3, 2, 2, 2, 154, 9, 3, 2, 2, 2, 155, 156, 7, 18, 2, 2, 156, 159, 5, 56, 29, 2, 157, 158, 7, 76, 2, 2, 158, 160, 5, 42, 22, 2, 159, 157, 3, 2, 2, 2, 159, 160, 3, 2, 2, 2, 160, 170, 3, 2, 2, 2, 161, 162, 7, 77, 2, 2, 162, 167, 5, 12, 7, 2, 163, 164, 7, 34, 2, 2, 164, 166, 5, 12, 7, 2, 165, 163, 3, 2, 2, 2, 166, 169, 3, 2, 2, 2, 167, 165, 3, 2, 2, 2, 167, 168, 3, 2, 2, 2, 168, 171, 3, 2, 2, 2, 169, 167, 3, 2, 2, 2, 170, 161, 3, 2, 2, 2, 170, 171, 3, 2, 2, 2, 171, 11, 3, 2, 2, 2, 172, 173, 5, 42, 22, 2, 173, 174, 7, 33, 2, 2, 174, 176, 3, 2, 2, 2, 175, 172, 3, 2, 2, 2, 175, 176, 3, 2, 2, 2, 176, 177, 3, 2, 2, 2, 177, 178, 5, 42, 22, 2, 178, 13, 3, 2, 2, 2, 179, 180, 7, 12, 2, 2, 180, 181, 5, 64, 33, 2, 181, 15, 3, 2, 2, 2, 182, 183, 7, 10, 2, 2, 183, 184, 5, 18, 10, 2, 184, 17, 3, 2, 2, 2, 185, 186, 8, 10, 1, 2, 186, 187, 7, 39, 2, 2, 187, 231, 5, 18, 10, 10, 188, 231, 5, 24, 13, 2, 189, 231, 5, 22, 12, 2, 190, 192, 5, 24, 13, 2, 191, 193, 7, 39, 2, 2, 192, 191, 3, 2, 2, 2, 192, 193, 3, 2, 2, 2, 193, 194, 3, 2, 2, 2, 194, 195, 7, 42, 2, 2, 195, 196, 7, 36, 2, 2, 196, 201, 5, 24, 13, 2, 197, 198, 7, 34, 2, 2, 198, 200, 5, 24, 13, 2, 199, 197, 3, 2, 2, 2, 200, 203, 3, 2, 2, 2, 201, 199, 3, 2, 2, 2, 201, 202, 3, 2, 2, 2, 202, 204, 3, 2, 2, 2, 203, 201, 3, 2, 2, 2, 204, 205, 7, 47, 2, 2, 205, 231, 3, 2, 2, 2, 206, 208, 7, 39, 2, 2, 207, 206, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 209, 3, 2, 2, 2, 209, 210, 7, 64, 2, 2, 210, 211, 7, 36, 2, 2, 211, 219, 5, 62, 32, 2, 212, 213, 7, 34, 2, 2, 213, 215, 5, 58, 30, 2, 214, 212, 3, 2, 2, 2, 215, 218, 3, 2, 2, 2, 216, 214, 3, 2, 2, 2, 216, 217, 3, 2, 2, 2, 217, 220, 3, 2, 2, 2, 218, 216, 3, 2, 2, 2, 219, 216, 3, 2, 2, 2, 219, 220, 3, 2, 2, 2, 220, 221, 3, 2, 2, 2, 221, 222, 7, 47, 2, 2, 222, 231, 3, 2, 2, 2, 223, 224, 5, 24, 13, 2, 224, 226, 7, 43, 2, 2, 225, 227, 7, 39, 2, 2, 226, 225, 3, 2, 2, 2, 226, 227, 3, 2, 2, 2, 227, 228, 3, 2, 2, 2, 228, 229, 7, 45, 2, 2, 229, 231, 3, 2, 2, 2, 230, 185, 3, 2, 2, 2, 230, 188, 3, 2, 2, 2, 230, 189, 3, 2, 2, 2, 230, 190, 3, 2, 2, 2, 230, 207, 3, 2, 2, 2, 230, 223, 3, 2, 2, 2, 231, 240, 3, 2, 2, 2, 232, 233, 12, 7, 2, 2, 233, 234, 7, 32, 2, 2, 234, 239, 5, 18, 10, 8, 235, 236, 12, 6, 2, 2, 236, 237, 7, 46, 2, 2, 237, 239, 5, 18, 10, 7, 238, 232, 3, 2, 2, 2, 238, 235, 3, 2, 2, 2, 239, 242, 3, 2, 2, 2, 240, 238, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 19, 3, 2, 2, 2, 242, 240, 3, 2, 2, 2, 243, 244, 8, 11, 1, 2, 244, 245, 7, 39, 2, 2, 245, 248, 5, 20, 11, 6, 246, 248, 5, 24, 13, 2, 247, 243, 3, 2, 2, 2, 247, 246, 3, 2, 2, 2, 248, 257, 3, 2, 2, 2, 249, 250, 12, 4, 2, 2, 250, 251, 7, 32, 2, 2, 251, 256, 5, 20, 11, 5, 252, 253, 12, 3, 2, 2, 253, 254, 7, 46, 2, 2, 254, 256, 5, 20, 11, 4, 255, 249, 3, 2, 2, 2, 255, 252, 3, 2, 2, 2, 256, 259, 3, 2, 2, 2, 257, 255, 3, 2, 2, 2, 257, 258, 3, 2, 2, 2, 258, 21, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 260, 262, 5, 24, 13, 2, 261, 263, 7, 39, 2, 2, 262, 261, 3, 2, 2, 2, 262, 263, 3, 2, 2, 2, 263, 264, 3, 2, 2, 2, 264, 265, 7, 40, 2, 2, 265, 266, 5, 110, 56, 2, 266, 275, 3, 2, 2, 2, 267, 269, 5, 24, 13, 2, 268, 270, 7, 39, 2, 2, 269, 268, 3, 2, 2, 2, 269, 270, 3, 2, 2, 2, 270, 271, 3, 2, 2, 2, 271, 272, 7, 41, 2, 2, 272, 273, 5, 110, 56, 2, 273, 275, 3, 2, 2, 2, 274, 260, 3, 2, 2, 2, 274, 267, 3, 2, 2, 2, 275, 23, 3, 2, 2, 2, 276, 279, 5, 32, 17, 2, 277, 279, 5, 26, 14, 2, 278, 276, 3, 2, 2, 2, 278, 277, 3, 2, 2, 2, 279, 25, 3, 2, 2, 2, 280, 281, 5, 32, 17, 2, 281, 282, 5, 112, 57, 2, 282, 283, 5, 32, 17, 2, 283, 27, 3, 2, 2, 2, 284, 285, 5, 70, 36, 2, 285, 294, 7, 36, 2, 2, 286, 291, 5, 58, 30, 2, 287, 288, 7, 34, 2, 2, 288, 290, 5, 58, 30, 2, 289, 287, 3, 2, 2, 2, 290, 293, 3, 2, 2, 2, 291, 289, 3, 2, 2, 2, 291, 292, 3, 2, 2, 2, 292, 295, 3, 2, 2, 2, 293, 291, 3, 2, 2, 2, 294, 286, 3, 2, 2, 2, 294, 295, 3, 2, 2, 2, 295, 296, 3, 2, 2, 2, 296, 297, 7, 47, 2, 2, 297, 29, 3, 2, 2, 2, 298, 299, 5, 68, 35, 2, 299, 308, 7, 36, 2, 2, 300, 305, 5, 60, 31, 2, 301, 302, 7, 34, 2, 2, 302, 304, 5, 60, 31, 2, 303, 301, 3, 2, 2, 2, 304, 307, 3, 2, 2, 2, 305, 303, 3, 2, 2, 2, 305, 306, 3, 2, 2, 2, 306, 309, 3, 2, 2, 2, 307, 305, 3, 2, 2, 2, 308, 300, 3, 2, 2, 2, 308, 309, 3, 2, 2, 2, 309, 310, 3, 2, 2, 2, 310, 311, 7, 47, 2, 2, 311, 31, 3, 2, 2, 2, 312, 313, 8, 17, 1, 2, 313, 319, 5, 34, 18, 2, 314, 319, 5, 28, 15, 2, 315, 319, 5, 30, 16, 2, 316, 317, 9, 2, 2, 2, 317, 319, 5, 32, 17, 5, 318, 312, 3, 2, 2, 2, 318, 314, 3, 2, 2, 2, 318, 315, 3, 2, 2, 2, 318, 316, 3, 2, 2, 2, 319, 328, 3, 2, 2, 2, 320, 321, 12, 4, 2, 2, 321, 322, 9, 3, 2, 2, 322, 327, 5, 32, 17, 5, 323, 324, 12, 3, 2, 2, 324, 325, 9, 2, 2, 2, 325, 327, 5, 32, 17, 4, 326, 320, 3, 2, 2, 2, 326, 323, 3, 2, 2, 2, 327, 330, 3, 2, 2, 2, 328, 326, 3, 2, 2, 2, 328, 329, 3, 2, 2, 2, 329, 33, 3, 2, 2, 2, 330, 328, 3, 2, 2, 2, 331, 352, 5, 72, 37, 2, 332, 352, 5, 62, 32, 2, 333, 334, 7, 36, 2, 2, 334, 335, 5, 20, 11, 2, 335, 336, 7, 47, 2, 2, 336, 352, 3, 2, 2, 2, 337, 338, 5, 66, 34, 2, 338, 347, 7, 36, 2, 2, 339, 344, 5, 20, 11, 2, 340, 341, 7, 34, 2, 2, 341, 343, 5, 20, 11, 2, 342, 340, 3, 2, 2, 2, 343, 346, 3, 2, 2, 2, 344, 342, 3, 2, 2, 2, 344, 345, 3, 2, 2, 2, 345, 348, 3, 2, 2, 2, 346, 344, 3, 2, 2, 2, 347, 339, 3, 2, 2, 2, 347, 348, 3, 2, 2, 2, 348, 349, 3, 2, 2, 2, 349, 350, 7, 47, 2, 2, 350, 352, 3, 2, 2, 2, 351, 331, 3, 2, 2, 2, 351, 332, 3, 2, 2, 2, 351, 333, 3, 2, 2, 2, 351, 337, 3, 2, 2, 2, 352, 35, 3, 2, 2, 2, 353, 354, 7, 8, 2, 2, 354, 355, 5, 38, 20, 2, 355, 37, 3, 2, 2, 2, 356, 361, 5, 40, 21, 2, 357, 358, 7, 34, 2, 2, 358, 360, 5, 40, 21, 2, 359, 357, 3, 2, 2, 2, 360, 363, 3, 2, 2, 2, 361, 359, 3, 2, 2, 2, 361, 362, 3, 2, 2, 2, 362, 39, 3, 2, 2, 2, 363, 361, 3, 2, 2, 2, 364, 370, 5, 20, 11, 2, 365, 366, 5, 44, 23, 2, 366, 367, 7, 33, 2, 2, 367, 368, 5, 20, 11, 2, 368, 370, 3, 2, 2, 2, 369, 364, 3, 2, 2, 2, 369, 365, 3, 2, 2, 2, 370, 41, 3, 2, 2, 2, 371, 372, 9, 4, 2, 2, 372, 43, 3, 2, 2, 2, 373, 374, 5, 66, 34, 2, 374, 45, 3, 2, 2, 2, 375, 376, 7, 7, 2, 2, 376, 381, 5, 54, 28, 2, 377, 378, 7, 34, 2, 2, 378, 380, 5, 54, 28, 2, 379, 377, 3, 2, 2, 2, 380, 383, 3, 2, 2, 2, 381, 379, 3, 2, 2, 2, 381, 382, 3, 2, 2, 2, 382, 385, 3, 2, 2, 2, 383, 381, 3, 2, 2, 2, 384, 386, 5, 48, 25, 2, 385, 384, 3, 2, 2, 2, 385, 386, 3, 2, 2, 2, 386, 47, 3, 2, 2, 2, 387, 388, 7, 37, 2, 2, 388, 389, 7, 70, 2, 2, 389, 394, 5, 54, 28, 2, 390, 391, 7, 34, 2, 2, 391, 393, 5, 54, 28, 2, 392, 390, 3, 2, 2, 2, 393, 396, 3, 2, 2, 2, 394, 392, 3, 2, 2, 2, 394, 395, 3, 2, 2, 2, 395, 397, 3, 2, 2, 2, 396, 394, 3, 2, 2, 2, 397, 398, 7, 38, 2, 2, 398, 49, 3, 2, 2, 2, 399, 400, 7, 5, 2, 2, 400, 401, 5, 38, 20, 2, 401, 51, 3, 2, 2, 2, 402, 404, 7, 9, 2, 2, 403, 405, 5, 38, 20, 2, 404, 403, 3, 2, 2, 2, 404, 405, 3, 2, 2, 2, 405, 408, 3, 2, 2, 2, 406, 407, 7, 30, 2, 2, 407, 409, 5, 64, 33, 2, 408, 406, 3, 2, 2, 2, 408, 409, 3, 2, 2, 2, 409, 53, 3, 2, 2, 2, 410, 411, 9, 5, 2, 2, 411, 55, 3, 2, 2, 2, 412, 413, 9, 4, 2, 2, 413, 57, 3, 2, 2, 2, 414, 418, 5, 62, 32, 2, 415, 418, 5, 110, 56, 2, 416, 418, 5, 104, 53, 2, 417, 414, 3, 2, 2, 2, 417, 415, 3, 2, 2, 2, 417, 416, 3, 2, 2, 2, 418, 59, 3, 2, 2, 2, 419, 428, 5, 62, 32, 2, 420, 428, 5, 110, 56, 2, 421, 428, 5, 104, 53, 2, 422, 428, 5, 32, 17, 2, 423, 424, 5, 104, 53, 2, 424, 425, 7, 31, 2, 2, 425, 428, 3, 2, 2, 2, 426, 428, 5, 26, 14, 2, 427, 419, 3, 2, 2, 2, 427, 420, 3, 2, 2, 2, 427, 421, 3, 2, 2, 2, 427, 422, 3, 2, 2, 2, 427, 423, 3, 2, 2, 2, 427, 426, 3, 2, 2, 2, 428, 61, 3, 2, 2, 2, 429, 434, 5, 66, 34, 2, 430, 431, 7, 35, 2, 2, 431, 433, 5, 66, 34, 2, 432, 430, 3, 2, 2, 2, 433, 436, 3, 2, 2, 2, 434, 432, 3, 2, 2, 2, 434, 435, 3, 2, 2, 2, 435, 63, 3, 2, 2, 2, 436, 434, 3, 2, 2, 2, 437, 442, 5, 62, 32, 2, 438, 439, 7, 34, 2, 2, 439, 441, 5, 62, 32, 2, 440, 438, 3, 2, 2, 2, 441, 444, 3, 2, 2, 2, 442, 440, 3, 2, 2, 2, 442, 443, 3, 2, 2, 2, 443, 65, 3, 2, 2, 2, 444, 442, 3, 2, 2, 2, 445, 446, 9, 6, 2, 2, 446, 67, 3, 2, 2, 2, 447, 448, 7, 62, 2, 2, 448, 69, 3, 2, 2, 2, 449, 450, 7, 63, 2, 2, 450, 71, 3, 2, 2, 2, 451, 489, 7, 45, 2, 2, 452, 489, 5, 74, 38, 2, 453, 489, 5, 102, 52, 2, 454, 489, 5, 110, 56, 2, 455, 456, 7, 37, 2, 2, 456, 461, 5, 74, 38, 2, 457, 458, 7, 34, 2, 2, 458, 460, 5, 74, 38, 2, 459, 457, 3, 2, 2, 2, 460, 463, 3, 2, 2, 2, 461, 459, 3, 2, 2, 2, 461, 462, 3, 2, 2, 2, 462, 464, 3, 2, 2, 2, 463, 461, 3, 2, 2, 2, 464, 465, 7, 38, 2, 2, 465, 489, 3, 2, 2, 2, 466, 467, 7, 37, 2, 2, 467, 472, 5, 102, 52, 2, 468, 469, 7, 34, 2, 2, 469, 471, 5, 102, 52, 2, 470, 468, 3, 2, 2, 2, 471, 474, 3, 2, 2, 2, 472, 470, 3, 2, 2, 2, 472, 473, 3, 2, 2, 2, 473, 475, 3, 2, 2, 2, 474, 472, 3, 2, 2, 2, 475, 476, 7, 38, 2, 2, 476, 489, 3, 2, 2, 2, 477, 478, 7, 37, 2, 2, 478, 483, 5, 110, 56, 2, 479, 480, 7, 34, 2, 2, 480, 482, 5, 110, 56, 2, 481, 479, 3, 2, 2, 2, 482, 485, 3, 2, 2, 2, 483, 481, 3, 2, 2, 2, 483, 484, 3, 2, 2, 2, 484, 486, 3, 2, 2, 2, 485, 483, 3, 2, 2, 2, 486, 487, 7, 38, 2, 2, 487, 489, 3, 2, 2, 2, 488, 451, 3, 2, 2, 2, 488, 452, 3, 2, 2, 2, 488, 453, 3, 2, 2, 2, 488, 454, 3, 2, 2, 2, 488, 455, 3, 2, 2, 2, 488, 466, 3, 2, 2, 2, 488, 477, 3, 2, 2, 2, 489, 73, 3, 2, 2, 2, 490, 493, 5, 106, 54, 2, 491, 493, 5, 108, 55, 2, 492, 490, 3, 2, 2, 2, 492, 491, 3, 2, 2, 2, 493, 75, 3, 2, 2, 2, 494, 495, 7, 13, 2, 2, 495, 496, 7, 28, 2, 2, 496, 77, 3, 2, 2, 2, 497, 498, 7, 11, 2, 2, 498, 503, 5, 80, 41, 2, 499, 500, 7, 34, 2, 2, 500, 502, 5, 80, 41, 2, 501, 499, 3, 2, 2, 2, 502, 505, 3, 2, 2, 2, 503, 501, 3, 2, 2, 2, 503, 504, 3, 2, 2, 2, 504, 79, 3, 2, 2, 2, 505, 503, 3, 2, 2, 2, 506, 508, 5, 20, 11, 2, 507, 509, 7, 59, 2, 2, 508, 507, 3, 2, 2, 2, 508, 509, 3, 2, 2, 2, 509, 512, 3, 2, 2, 2, 510, 511, 7, 60, 2, 2, 511, 513, 7, 61, 2, 2, 512, 510, 3, 2, 2, 2, 512, 513, 3, 2, 2, 2, 513, 81, 3, 2, 2, 2, 514, 515, 7, 14, 2, 2, 515, 516, 5, 64, 33, 2, 516, 83, 3, 2, 2, 2, 517, 518, 7, 19, 2, 2, 518, 519, 5, 64, 33, 2, 519, 85, 3, 2, 2, 2, 520, 521, 7, 15, 2, 2, 521, 522, 5, 64, 33, 2, 522, 87, 3, 2, 2, 2, 523, 528, 5, 66, 34, 2, 524, 525, 7, 35, 2, 2, 525, 527, 5, 66, 34, 2, 526, 524, 3, 2, 2, 2, 527, 530, 3, 2, 2, 2, 528, 526, 3, 2, 2, 2, 528, 529, 3, 2, 2, 2, 529, 89, 3, 2, 2, 2, 530, 528, 3, 2, 2, 2, 531, 532, 7, 16, 2, 2, 532, 537, 5, 92, 47, 2, 533, 534, 7, 34, 2, 2, 534, 536, 5, 92, 47, 2, 535, 533, 3, 2, 2, 2, 536, 539, 3, 2, 2, 2, 537, 535, 3, 2, 2, 2, 537, 538, 3, 2, 2, 2, 538, 91, 3, 2, 2, 2, 539, 537, 3, 2, 2, 2, 540, 541, 5, 62, 32, 2, 541, 542, 7, 44, 2, 2, 542, 543, 5, 88, 45, 2, 543, 93, 3, 2, 2, 2, 544, 545, 7, 3, 2, 2, 545, 546, 5, 64, 33, 2, 546, 548, 5, 110, 56, 2, 547, 549, 5, 98, 50, 2, 548, 547, 3, 2, 2, 2, 548, 549, 3, 2, 2, 2, 549, 95, 3, 2, 2, 2, 550, 551, 7, 4, 2, 2, 551, 552, 5, 64, 33, 2, 552, 553, 5, 110, 56, 2, 553, 97, 3, 2, 2, 2, 554, 559, 5, 100, 51, 2, 555, 556, 7, 34, 2, 2, 556, 558, 5, 100, 51, 2, 557, 555, 3, 2, 2, 2, 558, 561, 3, 2, 2, 2, 559, 557, 3, 2, 2, 2, 559, 560, 3, 2, 2, 2, 560, 99, 3, 2, 2, 2, 561, 559, 3, 2, 2, 2, 562, 563, 5, 66, 34, 2, 563, 564, 7, 33, 2, 2, 564, 565, 5, 72, 37, 2, 565, 101, 3, 2, 2, 2, 566, 567, 7, 51, 2, 2, 567, 103, 3, 2, 2, 2, 568, 571, 7, 29, 2, 2, 569, 571, 7, 28, 2, 2, 570, 568, 3, 2, 2, 2, 570, 569, 3, 2, 2, 2, 571, 105, 3, 2, 2, 2, 572, 573, 7, 29, 2, 2, 573, 107, 3, 2, 2, 2, 574, 575, 7, 28, 2, 2, 575, 109, 3, 2, 2, 2, 576, 577, 7, 27, 2, 2, 577, 111, 3, 2, 2, 2, 578, 579, 7, 52, 2, 2, 579, 113, 3, 2, 2, 2, 580, 581, 7, 6, 2, 2, 581, 582, 5, 116, 59, 2, 582, 115, 3, 2, 2, 2, 583, 584, 7, 37, 2, 2, 584, 585, 5, 4, 3, 2, 585, 586, 7, 38, 2, 2, 586, 117, 3, 2, 2, 2, 587, 588, 7, 17, 2, 2, 588, 592, 7, 49, 2, 2, 589, 590, 7, 17, 2, 2, 590, 592, 7, 50, 2, 2, 591, 587, 3, 2, 2, 2, 591, 589, 3, 2, 2, 2, 592, 119, 3, 2, 2, 2, 60, 131, 138, 153, 159, 167, 170, 175, 192, 201, 207, 216, 219, 226, 230, 238, 240, 247, 255, 257, 262, 269, 274, 278, 291, 294, 305, 308, 318, 326, 328, 344, 347, 351, 361, 369, 381, 385, 394, 404, 408, 417, 427, 434, 442, 461, 472, 483, 488, 492, 503, 508, 512, 528, 537, 548, 559, 570, 591] \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens b/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens index c2dafff2f222c..b72e97b9a2961 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens @@ -1,74 +1,98 @@ -EVAL=1 -EXPLAIN=2 -FROM=3 -ROW=4 -STATS=5 -WHERE=6 -SORT=7 -LIMIT=8 -PROJECT=9 -LINE_COMMENT=10 -MULTILINE_COMMENT=11 -WS=12 -PIPE=13 -STRING=14 -INTEGER_LITERAL=15 -DECIMAL_LITERAL=16 -BY=17 -AND=18 -ASSIGN=19 -COMMA=20 -DOT=21 -LP=22 -OPENING_BRACKET=23 -CLOSING_BRACKET=24 -NOT=25 -NULL=26 -OR=27 -RP=28 -BOOLEAN_VALUE=29 -COMPARISON_OPERATOR=30 -PLUS=31 -MINUS=32 -ASTERISK=33 -SLASH=34 -PERCENT=35 -ORDERING=36 -NULLS_ORDERING=37 -NULLS_ORDERING_DIRECTION=38 -UNARY_FUNCTION=39 -UNQUOTED_IDENTIFIER=40 -QUOTED_IDENTIFIER=41 -EXPR_LINE_COMMENT=42 -EXPR_MULTILINE_COMMENT=43 -EXPR_WS=44 -SRC_UNQUOTED_IDENTIFIER=45 -SRC_QUOTED_IDENTIFIER=46 -SRC_LINE_COMMENT=47 -SRC_MULTILINE_COMMENT=48 -SRC_WS=49 -'eval'=1 -'explain'=2 -'from'=3 -'row'=4 -'stats'=5 -'where'=6 -'sort'=7 -'limit'=8 -'project'=9 -'by'=17 -'and'=18 -'.'=21 -'('=22 -'['=23 -']'=24 -'not'=25 -'null'=26 -'or'=27 -')'=28 -'+'=31 -'-'=32 -'*'=33 -'/'=34 -'%'=35 -'nulls'=37 +DISSECT=1 +GROK=2 +EVAL=3 +EXPLAIN=4 +FROM=5 +ROW=6 +STATS=7 +WHERE=8 +SORT=9 +MV_EXPAND=10 +LIMIT=11 +PROJECT=12 +DROP=13 +RENAME=14 +SHOW=15 +ENRICH=16 +KEEP=17 +LINE_COMMENT=18 +MULTILINE_COMMENT=19 +WS=20 +EXPLAIN_WS=21 +EXPLAIN_LINE_COMMENT=22 +EXPLAIN_MULTILINE_COMMENT=23 +PIPE=24 +STRING=25 +INTEGER_LITERAL=26 +DECIMAL_LITERAL=27 +BY=28 +DATE_LITERAL=29 +AND=30 +ASSIGN=31 +COMMA=32 +DOT=33 +LP=34 +OPENING_BRACKET=35 +CLOSING_BRACKET=36 +NOT=37 +LIKE=38 +RLIKE=39 +IN=40 +IS=41 +AS=42 +NULL=43 +OR=44 +RP=45 +UNDERSCORE=46 +INFO=47 +FUNCTIONS=48 +BOOLEAN_VALUE=49 +COMPARISON_OPERATOR=50 +PLUS=51 +MINUS=52 +ASTERISK=53 +SLASH=54 +PERCENT=55 +TEN=56 +ORDERING=57 +NULLS_ORDERING=58 +NULLS_ORDERING_DIRECTION=59 +MATH_FUNCTION=60 +UNARY_FUNCTION=61 +WHERE_FUNCTIONS=62 +UNQUOTED_IDENTIFIER=63 +QUOTED_IDENTIFIER=64 +EXPR_LINE_COMMENT=65 +EXPR_MULTILINE_COMMENT=66 +EXPR_WS=67 +METADATA=68 +SRC_UNQUOTED_IDENTIFIER=69 +SRC_QUOTED_IDENTIFIER=70 +SRC_LINE_COMMENT=71 +SRC_MULTILINE_COMMENT=72 +SRC_WS=73 +ON=74 +WITH=75 +ENR_UNQUOTED_IDENTIFIER=76 +ENR_QUOTED_IDENTIFIER=77 +ENR_LINE_COMMENT=78 +ENR_MULTILINE_COMMENT=79 +ENR_WS=80 +EXPLAIN_PIPE=81 +'by'=28 +'and'=30 +'.'=33 +'('=34 +']'=36 +'or'=44 +')'=45 +'_'=46 +'info'=47 +'functions'=48 +'+'=51 +'-'=52 +'*'=53 +'/'=54 +'%'=55 +'10'=56 +'nulls'=58 diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.ts b/packages/kbn-monaco/src/esql/antlr/esql_parser.ts index de825a0b3698e..e70ad71c58ba1 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.ts +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.ts @@ -24,123 +24,192 @@ import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; import * as Utils from "antlr4ts/misc/Utils"; -import { esql_parserListener } from "./esql_parser_listener"; +import { esql_parserListener } from "./esql_parserListener"; export class esql_parser extends Parser { - public static readonly EVAL = 1; - public static readonly EXPLAIN = 2; - public static readonly FROM = 3; - public static readonly ROW = 4; - public static readonly STATS = 5; - public static readonly WHERE = 6; - public static readonly SORT = 7; - public static readonly LIMIT = 8; - public static readonly PROJECT = 9; - public static readonly LINE_COMMENT = 10; - public static readonly MULTILINE_COMMENT = 11; - public static readonly WS = 12; - public static readonly PIPE = 13; - public static readonly STRING = 14; - public static readonly INTEGER_LITERAL = 15; - public static readonly DECIMAL_LITERAL = 16; - public static readonly BY = 17; - public static readonly AND = 18; - public static readonly ASSIGN = 19; - public static readonly COMMA = 20; - public static readonly DOT = 21; - public static readonly LP = 22; - public static readonly OPENING_BRACKET = 23; - public static readonly CLOSING_BRACKET = 24; - public static readonly NOT = 25; - public static readonly NULL = 26; - public static readonly OR = 27; - public static readonly RP = 28; - public static readonly BOOLEAN_VALUE = 29; - public static readonly COMPARISON_OPERATOR = 30; - public static readonly PLUS = 31; - public static readonly MINUS = 32; - public static readonly ASTERISK = 33; - public static readonly SLASH = 34; - public static readonly PERCENT = 35; - public static readonly ORDERING = 36; - public static readonly NULLS_ORDERING = 37; - public static readonly NULLS_ORDERING_DIRECTION = 38; - public static readonly UNARY_FUNCTION = 39; - public static readonly UNQUOTED_IDENTIFIER = 40; - public static readonly QUOTED_IDENTIFIER = 41; - public static readonly EXPR_LINE_COMMENT = 42; - public static readonly EXPR_MULTILINE_COMMENT = 43; - public static readonly EXPR_WS = 44; - public static readonly SRC_UNQUOTED_IDENTIFIER = 45; - public static readonly SRC_QUOTED_IDENTIFIER = 46; - public static readonly SRC_LINE_COMMENT = 47; - public static readonly SRC_MULTILINE_COMMENT = 48; - public static readonly SRC_WS = 49; + public static readonly DISSECT = 1; + public static readonly GROK = 2; + public static readonly EVAL = 3; + public static readonly EXPLAIN = 4; + public static readonly FROM = 5; + public static readonly ROW = 6; + public static readonly STATS = 7; + public static readonly WHERE = 8; + public static readonly SORT = 9; + public static readonly MV_EXPAND = 10; + public static readonly LIMIT = 11; + public static readonly PROJECT = 12; + public static readonly DROP = 13; + public static readonly RENAME = 14; + public static readonly SHOW = 15; + public static readonly ENRICH = 16; + public static readonly KEEP = 17; + public static readonly LINE_COMMENT = 18; + public static readonly MULTILINE_COMMENT = 19; + public static readonly WS = 20; + public static readonly EXPLAIN_WS = 21; + public static readonly EXPLAIN_LINE_COMMENT = 22; + public static readonly EXPLAIN_MULTILINE_COMMENT = 23; + public static readonly PIPE = 24; + public static readonly STRING = 25; + public static readonly INTEGER_LITERAL = 26; + public static readonly DECIMAL_LITERAL = 27; + public static readonly BY = 28; + public static readonly DATE_LITERAL = 29; + public static readonly AND = 30; + public static readonly ASSIGN = 31; + public static readonly COMMA = 32; + public static readonly DOT = 33; + public static readonly LP = 34; + public static readonly OPENING_BRACKET = 35; + public static readonly CLOSING_BRACKET = 36; + public static readonly NOT = 37; + public static readonly LIKE = 38; + public static readonly RLIKE = 39; + public static readonly IN = 40; + public static readonly IS = 41; + public static readonly AS = 42; + public static readonly NULL = 43; + public static readonly OR = 44; + public static readonly RP = 45; + public static readonly UNDERSCORE = 46; + public static readonly INFO = 47; + public static readonly FUNCTIONS = 48; + public static readonly BOOLEAN_VALUE = 49; + public static readonly COMPARISON_OPERATOR = 50; + public static readonly PLUS = 51; + public static readonly MINUS = 52; + public static readonly ASTERISK = 53; + public static readonly SLASH = 54; + public static readonly PERCENT = 55; + public static readonly TEN = 56; + public static readonly ORDERING = 57; + public static readonly NULLS_ORDERING = 58; + public static readonly NULLS_ORDERING_DIRECTION = 59; + public static readonly MATH_FUNCTION = 60; + public static readonly UNARY_FUNCTION = 61; + public static readonly WHERE_FUNCTIONS = 62; + public static readonly UNQUOTED_IDENTIFIER = 63; + public static readonly QUOTED_IDENTIFIER = 64; + public static readonly EXPR_LINE_COMMENT = 65; + public static readonly EXPR_MULTILINE_COMMENT = 66; + public static readonly EXPR_WS = 67; + public static readonly METADATA = 68; + public static readonly SRC_UNQUOTED_IDENTIFIER = 69; + public static readonly SRC_QUOTED_IDENTIFIER = 70; + public static readonly SRC_LINE_COMMENT = 71; + public static readonly SRC_MULTILINE_COMMENT = 72; + public static readonly SRC_WS = 73; + public static readonly ON = 74; + public static readonly WITH = 75; + public static readonly ENR_UNQUOTED_IDENTIFIER = 76; + public static readonly ENR_QUOTED_IDENTIFIER = 77; + public static readonly ENR_LINE_COMMENT = 78; + public static readonly ENR_MULTILINE_COMMENT = 79; + public static readonly ENR_WS = 80; + public static readonly EXPLAIN_PIPE = 81; public static readonly RULE_singleStatement = 0; public static readonly RULE_query = 1; public static readonly RULE_sourceCommand = 2; public static readonly RULE_processingCommand = 3; - public static readonly RULE_whereCommand = 4; - public static readonly RULE_booleanExpression = 5; - public static readonly RULE_valueExpression = 6; - public static readonly RULE_comparison = 7; - public static readonly RULE_mathFn = 8; - public static readonly RULE_operatorExpression = 9; - public static readonly RULE_primaryExpression = 10; - public static readonly RULE_rowCommand = 11; - public static readonly RULE_fields = 12; - public static readonly RULE_field = 13; - public static readonly RULE_userVariable = 14; - public static readonly RULE_fromCommand = 15; - public static readonly RULE_evalCommand = 16; - public static readonly RULE_statsCommand = 17; - public static readonly RULE_sourceIdentifier = 18; - public static readonly RULE_functionExpressionArgument = 19; - public static readonly RULE_qualifiedName = 20; - public static readonly RULE_qualifiedNames = 21; - public static readonly RULE_identifier = 22; - public static readonly RULE_functionIdentifier = 23; - public static readonly RULE_constant = 24; - public static readonly RULE_limitCommand = 25; - public static readonly RULE_sortCommand = 26; - public static readonly RULE_orderExpression = 27; - public static readonly RULE_projectCommand = 28; - public static readonly RULE_projectClause = 29; - public static readonly RULE_booleanValue = 30; - public static readonly RULE_number = 31; - public static readonly RULE_string = 32; - public static readonly RULE_comparisonOperator = 33; - public static readonly RULE_explainCommand = 34; - public static readonly RULE_subqueryExpression = 35; + public static readonly RULE_enrichCommand = 4; + public static readonly RULE_enrichWithClause = 5; + public static readonly RULE_mvExpandCommand = 6; + public static readonly RULE_whereCommand = 7; + public static readonly RULE_whereBooleanExpression = 8; + public static readonly RULE_booleanExpression = 9; + public static readonly RULE_regexBooleanExpression = 10; + public static readonly RULE_valueExpression = 11; + public static readonly RULE_comparison = 12; + public static readonly RULE_mathFn = 13; + public static readonly RULE_mathEvalFn = 14; + public static readonly RULE_operatorExpression = 15; + public static readonly RULE_primaryExpression = 16; + public static readonly RULE_rowCommand = 17; + public static readonly RULE_fields = 18; + public static readonly RULE_field = 19; + public static readonly RULE_enrichFieldIdentifier = 20; + public static readonly RULE_userVariable = 21; + public static readonly RULE_fromCommand = 22; + public static readonly RULE_metadata = 23; + public static readonly RULE_evalCommand = 24; + public static readonly RULE_statsCommand = 25; + public static readonly RULE_sourceIdentifier = 26; + public static readonly RULE_enrichIdentifier = 27; + public static readonly RULE_functionExpressionArgument = 28; + public static readonly RULE_mathFunctionExpressionArgument = 29; + public static readonly RULE_qualifiedName = 30; + public static readonly RULE_qualifiedNames = 31; + public static readonly RULE_identifier = 32; + public static readonly RULE_mathFunctionIdentifier = 33; + public static readonly RULE_functionIdentifier = 34; + public static readonly RULE_constant = 35; + public static readonly RULE_numericValue = 36; + public static readonly RULE_limitCommand = 37; + public static readonly RULE_sortCommand = 38; + public static readonly RULE_orderExpression = 39; + public static readonly RULE_projectCommand = 40; + public static readonly RULE_keepCommand = 41; + public static readonly RULE_dropCommand = 42; + public static readonly RULE_renameVariable = 43; + public static readonly RULE_renameCommand = 44; + public static readonly RULE_renameClause = 45; + public static readonly RULE_dissectCommand = 46; + public static readonly RULE_grokCommand = 47; + public static readonly RULE_commandOptions = 48; + public static readonly RULE_commandOption = 49; + public static readonly RULE_booleanValue = 50; + public static readonly RULE_number = 51; + public static readonly RULE_decimalValue = 52; + public static readonly RULE_integerValue = 53; + public static readonly RULE_string = 54; + public static readonly RULE_comparisonOperator = 55; + public static readonly RULE_explainCommand = 56; + public static readonly RULE_subqueryExpression = 57; + public static readonly RULE_showCommand = 58; // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ - "singleStatement", "query", "sourceCommand", "processingCommand", "whereCommand", - "booleanExpression", "valueExpression", "comparison", "mathFn", "operatorExpression", - "primaryExpression", "rowCommand", "fields", "field", "userVariable", - "fromCommand", "evalCommand", "statsCommand", "sourceIdentifier", "functionExpressionArgument", - "qualifiedName", "qualifiedNames", "identifier", "functionIdentifier", - "constant", "limitCommand", "sortCommand", "orderExpression", "projectCommand", - "projectClause", "booleanValue", "number", "string", "comparisonOperator", - "explainCommand", "subqueryExpression", + "singleStatement", "query", "sourceCommand", "processingCommand", "enrichCommand", + "enrichWithClause", "mvExpandCommand", "whereCommand", "whereBooleanExpression", + "booleanExpression", "regexBooleanExpression", "valueExpression", "comparison", + "mathFn", "mathEvalFn", "operatorExpression", "primaryExpression", "rowCommand", + "fields", "field", "enrichFieldIdentifier", "userVariable", "fromCommand", + "metadata", "evalCommand", "statsCommand", "sourceIdentifier", "enrichIdentifier", + "functionExpressionArgument", "mathFunctionExpressionArgument", "qualifiedName", + "qualifiedNames", "identifier", "mathFunctionIdentifier", "functionIdentifier", + "constant", "numericValue", "limitCommand", "sortCommand", "orderExpression", + "projectCommand", "keepCommand", "dropCommand", "renameVariable", "renameCommand", + "renameClause", "dissectCommand", "grokCommand", "commandOptions", "commandOption", + "booleanValue", "number", "decimalValue", "integerValue", "string", "comparisonOperator", + "explainCommand", "subqueryExpression", "showCommand", ]; private static readonly _LITERAL_NAMES: Array = [ - undefined, "'eval'", "'explain'", "'from'", "'row'", "'stats'", "'where'", - "'sort'", "'limit'", "'project'", undefined, undefined, undefined, undefined, - undefined, undefined, undefined, "'by'", "'and'", undefined, undefined, - "'.'", "'('", "'['", "']'", "'not'", "'null'", "'or'", "')'", undefined, - undefined, "'+'", "'-'", "'*'", "'/'", "'%'", undefined, "'nulls'", + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + undefined, undefined, undefined, undefined, undefined, undefined, undefined, + "'by'", undefined, "'and'", undefined, undefined, "'.'", "'('", undefined, + "']'", undefined, undefined, undefined, undefined, undefined, undefined, + undefined, "'or'", "')'", "'_'", "'info'", "'functions'", undefined, undefined, + "'+'", "'-'", "'*'", "'/'", "'%'", "'10'", undefined, "'nulls'", ]; private static readonly _SYMBOLIC_NAMES: Array = [ - undefined, "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", "WHERE", "SORT", - "LIMIT", "PROJECT", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", - "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASSIGN", - "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", "NOT", "NULL", - "OR", "RP", "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", "ASTERISK", - "SLASH", "PERCENT", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", - "UNARY_FUNCTION", "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", - "EXPR_MULTILINE_COMMENT", "EXPR_WS", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", - "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", "SRC_WS", + undefined, "DISSECT", "GROK", "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", + "WHERE", "SORT", "MV_EXPAND", "LIMIT", "PROJECT", "DROP", "RENAME", "SHOW", + "ENRICH", "KEEP", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "EXPLAIN_WS", + "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "PIPE", "STRING", + "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "DATE_LITERAL", "AND", "ASSIGN", + "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", "NOT", "LIKE", + "RLIKE", "IN", "IS", "AS", "NULL", "OR", "RP", "UNDERSCORE", "INFO", "FUNCTIONS", + "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", "ASTERISK", "SLASH", + "PERCENT", "TEN", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", + "MATH_FUNCTION", "UNARY_FUNCTION", "WHERE_FUNCTIONS", "UNQUOTED_IDENTIFIER", + "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", + "METADATA", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", + "SRC_MULTILINE_COMMENT", "SRC_WS", "ON", "WITH", "ENR_UNQUOTED_IDENTIFIER", + "ENR_QUOTED_IDENTIFIER", "ENR_LINE_COMMENT", "ENR_MULTILINE_COMMENT", + "ENR_WS", "EXPLAIN_PIPE", ]; public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(esql_parser._LITERAL_NAMES, esql_parser._SYMBOLIC_NAMES, []); @@ -171,9 +240,9 @@ export class esql_parser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 72; + this.state = 118; this.query(0); - this.state = 73; + this.state = 119; this.match(esql_parser.EOF); } } @@ -215,11 +284,11 @@ export class esql_parser extends Parser { this._ctx = _localctx; _prevctx = _localctx; - this.state = 76; + this.state = 122; this.sourceCommand(); } this._ctx._stop = this._input.tryLT(-1); - this.state = 83; + this.state = 129; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 0, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -232,18 +301,18 @@ export class esql_parser extends Parser { { _localctx = new CompositeQueryContext(new QueryContext(_parentctx, _parentState)); this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_query); - this.state = 78; + this.state = 124; if (!(this.precpred(this._ctx, 1))) { throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); } - this.state = 79; + this.state = 125; this.match(esql_parser.PIPE); - this.state = 80; + this.state = 126; this.processingCommand(); } } } - this.state = 85; + this.state = 131; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 0, this._ctx); } @@ -268,30 +337,37 @@ export class esql_parser extends Parser { let _localctx: SourceCommandContext = new SourceCommandContext(this._ctx, this.state); this.enterRule(_localctx, 4, esql_parser.RULE_sourceCommand); try { - this.state = 89; + this.state = 136; this._errHandler.sync(this); switch (this._input.LA(1)) { case esql_parser.EXPLAIN: this.enterOuterAlt(_localctx, 1); { - this.state = 86; + this.state = 132; this.explainCommand(); } break; case esql_parser.FROM: this.enterOuterAlt(_localctx, 2); { - this.state = 87; + this.state = 133; this.fromCommand(); } break; case esql_parser.ROW: this.enterOuterAlt(_localctx, 3); { - this.state = 88; + this.state = 134; this.rowCommand(); } break; + case esql_parser.SHOW: + this.enterOuterAlt(_localctx, 4); + { + this.state = 135; + this.showCommand(); + } + break; default: throw new NoViableAltException(this); } @@ -315,51 +391,100 @@ export class esql_parser extends Parser { let _localctx: ProcessingCommandContext = new ProcessingCommandContext(this._ctx, this.state); this.enterRule(_localctx, 6, esql_parser.RULE_processingCommand); try { - this.state = 97; + this.state = 151; this._errHandler.sync(this); switch (this._input.LA(1)) { case esql_parser.EVAL: this.enterOuterAlt(_localctx, 1); { - this.state = 91; + this.state = 138; this.evalCommand(); } break; case esql_parser.LIMIT: this.enterOuterAlt(_localctx, 2); { - this.state = 92; + this.state = 139; this.limitCommand(); } break; case esql_parser.PROJECT: this.enterOuterAlt(_localctx, 3); { - this.state = 93; + this.state = 140; this.projectCommand(); } break; - case esql_parser.SORT: + case esql_parser.KEEP: this.enterOuterAlt(_localctx, 4); { - this.state = 94; + this.state = 141; + this.keepCommand(); + } + break; + case esql_parser.RENAME: + this.enterOuterAlt(_localctx, 5); + { + this.state = 142; + this.renameCommand(); + } + break; + case esql_parser.DROP: + this.enterOuterAlt(_localctx, 6); + { + this.state = 143; + this.dropCommand(); + } + break; + case esql_parser.DISSECT: + this.enterOuterAlt(_localctx, 7); + { + this.state = 144; + this.dissectCommand(); + } + break; + case esql_parser.GROK: + this.enterOuterAlt(_localctx, 8); + { + this.state = 145; + this.grokCommand(); + } + break; + case esql_parser.SORT: + this.enterOuterAlt(_localctx, 9); + { + this.state = 146; this.sortCommand(); } break; case esql_parser.STATS: - this.enterOuterAlt(_localctx, 5); + this.enterOuterAlt(_localctx, 10); { - this.state = 95; + this.state = 147; this.statsCommand(); } break; case esql_parser.WHERE: - this.enterOuterAlt(_localctx, 6); + this.enterOuterAlt(_localctx, 11); { - this.state = 96; + this.state = 148; this.whereCommand(); } break; + case esql_parser.MV_EXPAND: + this.enterOuterAlt(_localctx, 12); + { + this.state = 149; + this.mvExpandCommand(); + } + break; + case esql_parser.ENRICH: + this.enterOuterAlt(_localctx, 13); + { + this.state = 150; + this.enrichCommand(); + } + break; default: throw new NoViableAltException(this); } @@ -379,132 +504,58 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public whereCommand(): WhereCommandContext { - let _localctx: WhereCommandContext = new WhereCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 8, esql_parser.RULE_whereCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(esql_parser.WHERE); - this.state = 100; - this.booleanExpression(0); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - - public booleanExpression(): BooleanExpressionContext; - public booleanExpression(_p: number): BooleanExpressionContext; - // @RuleVersion(0) - public booleanExpression(_p?: number): BooleanExpressionContext { - if (_p === undefined) { - _p = 0; - } - - let _parentctx: ParserRuleContext = this._ctx; - let _parentState: number = this.state; - let _localctx: BooleanExpressionContext = new BooleanExpressionContext(this._ctx, _parentState); - let _prevctx: BooleanExpressionContext = _localctx; - let _startState: number = 10; - this.enterRecursionRule(_localctx, 10, esql_parser.RULE_booleanExpression, _p); + public enrichCommand(): EnrichCommandContext { + let _localctx: EnrichCommandContext = new EnrichCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 8, esql_parser.RULE_enrichCommand); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 106; + this.state = 153; + this.match(esql_parser.ENRICH); + this.state = 154; + _localctx._policyName = this.enrichIdentifier(); + this.state = 157; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.NOT: - { - this.state = 103; - this.match(esql_parser.NOT); - this.state = 104; - this.booleanExpression(4); - } - break; - case esql_parser.STRING: - case esql_parser.INTEGER_LITERAL: - case esql_parser.DECIMAL_LITERAL: - case esql_parser.LP: - case esql_parser.NULL: - case esql_parser.BOOLEAN_VALUE: - case esql_parser.PLUS: - case esql_parser.MINUS: - case esql_parser.UNARY_FUNCTION: - case esql_parser.UNQUOTED_IDENTIFIER: - case esql_parser.QUOTED_IDENTIFIER: + switch ( this.interpreter.adaptivePredict(this._input, 3, this._ctx) ) { + case 1: { - this.state = 105; - this.valueExpression(); + this.state = 155; + this.match(esql_parser.ON); + this.state = 156; + _localctx._matchField = this.enrichFieldIdentifier(); } break; - default: - throw new NoViableAltException(this); } - this._ctx._stop = this._input.tryLT(-1); - this.state = 116; + this.state = 168; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - if (this._parseListeners != null) { - this.triggerExitRuleEvent(); - } - _prevctx = _localctx; - { - this.state = 114; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 4, this._ctx) ) { - case 1: + switch ( this.interpreter.adaptivePredict(this._input, 5, this._ctx) ) { + case 1: + { + this.state = 159; + this.match(esql_parser.WITH); + this.state = 160; + this.enrichWithClause(); + this.state = 165; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 4, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { { - _localctx = new BooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 108; - if (!(this.precpred(this._ctx, 2))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 2)"); - } - this.state = 109; - _localctx._operator = this.match(esql_parser.AND); - this.state = 110; - _localctx._right = this.booleanExpression(3); - } - break; - - case 2: { - _localctx = new BooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 111; - if (!(this.precpred(this._ctx, 1))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); + this.state = 161; + this.match(esql_parser.COMMA); + this.state = 162; + this.enrichWithClause(); } - this.state = 112; - _localctx._operator = this.match(esql_parser.OR); - this.state = 113; - _localctx._right = this.booleanExpression(2); } - break; - } } + this.state = 167; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 4, this._ctx); } - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); + } + break; } } } @@ -518,34 +569,32 @@ export class esql_parser extends Parser { } } finally { - this.unrollRecursionContexts(_parentctx); + this.exitRule(); } return _localctx; } // @RuleVersion(0) - public valueExpression(): ValueExpressionContext { - let _localctx: ValueExpressionContext = new ValueExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 12, esql_parser.RULE_valueExpression); + public enrichWithClause(): EnrichWithClauseContext { + let _localctx: EnrichWithClauseContext = new EnrichWithClauseContext(this._ctx, this.state); + this.enterRule(_localctx, 10, esql_parser.RULE_enrichWithClause); try { - this.state = 121; + this.enterOuterAlt(_localctx, 1); + { + this.state = 173; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 6, this._ctx) ) { case 1: - this.enterOuterAlt(_localctx, 1); { - this.state = 119; - this.operatorExpression(0); - } - break; - - case 2: - this.enterOuterAlt(_localctx, 2); - { - this.state = 120; - this.comparison(); + this.state = 170; + _localctx._newName = this.enrichFieldIdentifier(); + this.state = 171; + this.match(esql_parser.ASSIGN); } break; } + this.state = 175; + _localctx._enrichField = this.enrichFieldIdentifier(); + } } catch (re) { if (re instanceof RecognitionException) { @@ -562,18 +611,16 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public comparison(): ComparisonContext { - let _localctx: ComparisonContext = new ComparisonContext(this._ctx, this.state); - this.enterRule(_localctx, 14, esql_parser.RULE_comparison); + public mvExpandCommand(): MvExpandCommandContext { + let _localctx: MvExpandCommandContext = new MvExpandCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 12, esql_parser.RULE_mvExpandCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 123; - _localctx._left = this.operatorExpression(0); - this.state = 124; - this.comparisonOperator(); - this.state = 125; - _localctx._right = this.operatorExpression(0); + this.state = 177; + this.match(esql_parser.MV_EXPAND); + this.state = 178; + this.qualifiedNames(); } } catch (re) { @@ -591,45 +638,16 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public mathFn(): MathFnContext { - let _localctx: MathFnContext = new MathFnContext(this._ctx, this.state); - this.enterRule(_localctx, 16, esql_parser.RULE_mathFn); - let _la: number; + public whereCommand(): WhereCommandContext { + let _localctx: WhereCommandContext = new WhereCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 14, esql_parser.RULE_whereCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 127; - this.functionIdentifier(); - this.state = 128; - this.match(esql_parser.LP); - this.state = 137; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (((((_la - 14)) & ~0x1F) === 0 && ((1 << (_la - 14)) & ((1 << (esql_parser.STRING - 14)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 14)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 14)))) !== 0)) { - { - this.state = 129; - this.functionExpressionArgument(); - this.state = 134; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 130; - this.match(esql_parser.COMMA); - this.state = 131; - this.functionExpressionArgument(); - } - } - this.state = 136; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 139; - this.match(esql_parser.RP); + this.state = 180; + this.match(esql_parser.WHERE); + this.state = 181; + this.whereBooleanExpression(0); } } catch (re) { @@ -647,74 +665,164 @@ export class esql_parser extends Parser { return _localctx; } - public operatorExpression(): OperatorExpressionContext; - public operatorExpression(_p: number): OperatorExpressionContext; + public whereBooleanExpression(): WhereBooleanExpressionContext; + public whereBooleanExpression(_p: number): WhereBooleanExpressionContext; // @RuleVersion(0) - public operatorExpression(_p?: number): OperatorExpressionContext { + public whereBooleanExpression(_p?: number): WhereBooleanExpressionContext { if (_p === undefined) { _p = 0; } let _parentctx: ParserRuleContext = this._ctx; let _parentState: number = this.state; - let _localctx: OperatorExpressionContext = new OperatorExpressionContext(this._ctx, _parentState); - let _prevctx: OperatorExpressionContext = _localctx; - let _startState: number = 18; - this.enterRecursionRule(_localctx, 18, esql_parser.RULE_operatorExpression, _p); + let _localctx: WhereBooleanExpressionContext = new WhereBooleanExpressionContext(this._ctx, _parentState); + let _prevctx: WhereBooleanExpressionContext = _localctx; + let _startState: number = 16; + this.enterRecursionRule(_localctx, 16, esql_parser.RULE_whereBooleanExpression, _p); let _la: number; try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 146; + this.state = 228; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.STRING: - case esql_parser.INTEGER_LITERAL: - case esql_parser.DECIMAL_LITERAL: - case esql_parser.LP: - case esql_parser.NULL: - case esql_parser.BOOLEAN_VALUE: - case esql_parser.UNQUOTED_IDENTIFIER: - case esql_parser.QUOTED_IDENTIFIER: + switch ( this.interpreter.adaptivePredict(this._input, 13, this._ctx) ) { + case 1: { - this.state = 142; - this.primaryExpression(); + this.state = 184; + this.match(esql_parser.NOT); + this.state = 185; + this.whereBooleanExpression(8); } break; - case esql_parser.UNARY_FUNCTION: + + case 2: { - this.state = 143; - this.mathFn(); + this.state = 186; + this.valueExpression(); } break; - case esql_parser.PLUS: - case esql_parser.MINUS: + + case 3: { - this.state = 144; - _localctx._operator = this._input.LT(1); + this.state = 187; + this.regexBooleanExpression(); + } + break; + + case 4: + { + this.state = 188; + this.valueExpression(); + this.state = 190; + this._errHandler.sync(this); _la = this._input.LA(1); - if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { - _localctx._operator = this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; + if (_la === esql_parser.NOT) { + { + this.state = 189; + this.match(esql_parser.NOT); } + } - this._errHandler.reportMatch(this); - this.consume(); + this.state = 192; + this.match(esql_parser.IN); + this.state = 193; + this.match(esql_parser.LP); + this.state = 194; + this.valueExpression(); + this.state = 199; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === esql_parser.COMMA) { + { + { + this.state = 195; + this.match(esql_parser.COMMA); + this.state = 196; + this.valueExpression(); + } + } + this.state = 201; + this._errHandler.sync(this); + _la = this._input.LA(1); } - this.state = 145; - this.operatorExpression(3); + this.state = 202; + this.match(esql_parser.RP); + } + break; + + case 5: + { + this.state = 205; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === esql_parser.NOT) { + { + this.state = 204; + this.match(esql_parser.NOT); + } + } + + this.state = 207; + this.match(esql_parser.WHERE_FUNCTIONS); + this.state = 208; + this.match(esql_parser.LP); + this.state = 209; + this.qualifiedName(); + this.state = 217; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 11, this._ctx) ) { + case 1: + { + this.state = 214; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === esql_parser.COMMA) { + { + { + this.state = 210; + this.match(esql_parser.COMMA); + this.state = 211; + this.functionExpressionArgument(); + } + } + this.state = 216; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + break; + } + this.state = 219; + this.match(esql_parser.RP); + } + break; + + case 6: + { + this.state = 221; + this.valueExpression(); + this.state = 222; + this.match(esql_parser.IS); + this.state = 224; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === esql_parser.NOT) { + { + this.state = 223; + this.match(esql_parser.NOT); + } + } + + this.state = 226; + this.match(esql_parser.NULL); } break; - default: - throw new NoViableAltException(this); } this._ctx._stop = this._input.tryLT(-1); - this.state = 156; + this.state = 238; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 11, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -722,68 +830,166 @@ export class esql_parser extends Parser { } _prevctx = _localctx; { - this.state = 154; + this.state = 236; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 10, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 14, this._ctx) ) { case 1: { - _localctx = new OperatorExpressionContext(_parentctx, _parentState); + _localctx = new WhereBooleanExpressionContext(_parentctx, _parentState); _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 148; - if (!(this.precpred(this._ctx, 2))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 2)"); + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_whereBooleanExpression); + this.state = 230; + if (!(this.precpred(this._ctx, 5))) { + throw new FailedPredicateException(this, "this.precpred(this._ctx, 5)"); } - this.state = 149; - _localctx._operator = this._input.LT(1); - _la = this._input.LA(1); - if (!(((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & ((1 << (esql_parser.ASTERISK - 33)) | (1 << (esql_parser.SLASH - 33)) | (1 << (esql_parser.PERCENT - 33)))) !== 0))) { - _localctx._operator = this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } + this.state = 231; + _localctx._operator = this.match(esql_parser.AND); + this.state = 232; + _localctx._right = this.whereBooleanExpression(6); + } + break; - this._errHandler.reportMatch(this); - this.consume(); + case 2: + { + _localctx = new WhereBooleanExpressionContext(_parentctx, _parentState); + _localctx._left = _prevctx; + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_whereBooleanExpression); + this.state = 233; + if (!(this.precpred(this._ctx, 4))) { + throw new FailedPredicateException(this, "this.precpred(this._ctx, 4)"); } - this.state = 150; - _localctx._right = this.operatorExpression(3); + this.state = 234; + _localctx._operator = this.match(esql_parser.OR); + this.state = 235; + _localctx._right = this.whereBooleanExpression(5); + } + break; + } + } + } + this.state = 240; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public booleanExpression(): BooleanExpressionContext; + public booleanExpression(_p: number): BooleanExpressionContext; + // @RuleVersion(0) + public booleanExpression(_p?: number): BooleanExpressionContext { + if (_p === undefined) { + _p = 0; + } + + let _parentctx: ParserRuleContext = this._ctx; + let _parentState: number = this.state; + let _localctx: BooleanExpressionContext = new BooleanExpressionContext(this._ctx, _parentState); + let _prevctx: BooleanExpressionContext = _localctx; + let _startState: number = 18; + this.enterRecursionRule(_localctx, 18, esql_parser.RULE_booleanExpression, _p); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 245; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case esql_parser.NOT: + { + this.state = 242; + this.match(esql_parser.NOT); + this.state = 243; + this.booleanExpression(4); + } + break; + case esql_parser.STRING: + case esql_parser.INTEGER_LITERAL: + case esql_parser.DECIMAL_LITERAL: + case esql_parser.LP: + case esql_parser.OPENING_BRACKET: + case esql_parser.NULL: + case esql_parser.BOOLEAN_VALUE: + case esql_parser.PLUS: + case esql_parser.MINUS: + case esql_parser.ASTERISK: + case esql_parser.MATH_FUNCTION: + case esql_parser.UNARY_FUNCTION: + case esql_parser.UNQUOTED_IDENTIFIER: + case esql_parser.QUOTED_IDENTIFIER: + { + this.state = 244; + this.valueExpression(); + } + break; + default: + throw new NoViableAltException(this); + } + this._ctx._stop = this._input.tryLT(-1); + this.state = 255; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + if (this._parseListeners != null) { + this.triggerExitRuleEvent(); + } + _prevctx = _localctx; + { + this.state = 253; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 17, this._ctx) ) { + case 1: + { + _localctx = new BooleanExpressionContext(_parentctx, _parentState); + _localctx._left = _prevctx; + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); + this.state = 247; + if (!(this.precpred(this._ctx, 2))) { + throw new FailedPredicateException(this, "this.precpred(this._ctx, 2)"); + } + this.state = 248; + _localctx._operator = this.match(esql_parser.AND); + this.state = 249; + _localctx._right = this.booleanExpression(3); } break; case 2: { - _localctx = new OperatorExpressionContext(_parentctx, _parentState); + _localctx = new BooleanExpressionContext(_parentctx, _parentState); _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 151; + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); + this.state = 250; if (!(this.precpred(this._ctx, 1))) { throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); } - this.state = 152; - _localctx._operator = this._input.LT(1); - _la = this._input.LA(1); - if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { - _localctx._operator = this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - this.state = 153; - _localctx._right = this.operatorExpression(2); + this.state = 251; + _localctx._operator = this.match(esql_parser.OR); + this.state = 252; + _localctx._right = this.booleanExpression(2); } break; } } } - this.state = 158; + this.state = 257; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 11, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); } } } @@ -802,77 +1008,55 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public primaryExpression(): PrimaryExpressionContext { - let _localctx: PrimaryExpressionContext = new PrimaryExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 20, esql_parser.RULE_primaryExpression); + public regexBooleanExpression(): RegexBooleanExpressionContext { + let _localctx: RegexBooleanExpressionContext = new RegexBooleanExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 20, esql_parser.RULE_regexBooleanExpression); let _la: number; try { - this.state = 179; + this.state = 272; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 14, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 21, this._ctx) ) { case 1: this.enterOuterAlt(_localctx, 1); { - this.state = 159; - this.constant(); - } - break; - - case 2: - this.enterOuterAlt(_localctx, 2); - { - this.state = 160; - this.qualifiedName(); + this.state = 258; + this.valueExpression(); + this.state = 260; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === esql_parser.NOT) { + { + this.state = 259; + this.match(esql_parser.NOT); + } } - break; - case 3: - this.enterOuterAlt(_localctx, 3); - { - this.state = 161; - this.match(esql_parser.LP); - this.state = 162; - this.booleanExpression(0); - this.state = 163; - this.match(esql_parser.RP); + this.state = 262; + _localctx._kind = this.match(esql_parser.LIKE); + this.state = 263; + _localctx._pattern = this.string(); } break; - case 4: - this.enterOuterAlt(_localctx, 4); + case 2: + this.enterOuterAlt(_localctx, 2); { - this.state = 165; - this.identifier(); - this.state = 166; - this.match(esql_parser.LP); - this.state = 175; + this.state = 265; + this.valueExpression(); + this.state = 267; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 14)) & ~0x1F) === 0 && ((1 << (_la - 14)) & ((1 << (esql_parser.STRING - 14)) | (1 << (esql_parser.INTEGER_LITERAL - 14)) | (1 << (esql_parser.DECIMAL_LITERAL - 14)) | (1 << (esql_parser.LP - 14)) | (1 << (esql_parser.NOT - 14)) | (1 << (esql_parser.NULL - 14)) | (1 << (esql_parser.BOOLEAN_VALUE - 14)) | (1 << (esql_parser.PLUS - 14)) | (1 << (esql_parser.MINUS - 14)) | (1 << (esql_parser.UNARY_FUNCTION - 14)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 14)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 14)))) !== 0)) { + if (_la === esql_parser.NOT) { { - this.state = 167; - this.booleanExpression(0); - this.state = 172; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 168; - this.match(esql_parser.COMMA); - this.state = 169; - this.booleanExpression(0); - } - } - this.state = 174; - this._errHandler.sync(this); - _la = this._input.LA(1); - } + this.state = 266; + this.match(esql_parser.NOT); } } - this.state = 177; - this.match(esql_parser.RP); + this.state = 269; + _localctx._kind = this.match(esql_parser.RLIKE); + this.state = 270; + _localctx._pattern = this.string(); } break; } @@ -892,16 +1076,28 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public rowCommand(): RowCommandContext { - let _localctx: RowCommandContext = new RowCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 22, esql_parser.RULE_rowCommand); + public valueExpression(): ValueExpressionContext { + let _localctx: ValueExpressionContext = new ValueExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 22, esql_parser.RULE_valueExpression); try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 181; - this.match(esql_parser.ROW); - this.state = 182; - this.fields(); + this.state = 276; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 22, this._ctx) ) { + case 1: + this.enterOuterAlt(_localctx, 1); + { + this.state = 274; + this.operatorExpression(0); + } + break; + + case 2: + this.enterOuterAlt(_localctx, 2); + { + this.state = 275; + this.comparison(); + } + break; } } catch (re) { @@ -919,33 +1115,18 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public fields(): FieldsContext { - let _localctx: FieldsContext = new FieldsContext(this._ctx, this.state); - this.enterRule(_localctx, 24, esql_parser.RULE_fields); + public comparison(): ComparisonContext { + let _localctx: ComparisonContext = new ComparisonContext(this._ctx, this.state); + this.enterRule(_localctx, 24, esql_parser.RULE_comparison); try { - let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 184; - this.field(); - this.state = 189; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 185; - this.match(esql_parser.COMMA); - this.state = 186; - this.field(); - } - } - } - this.state = 191; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); - } + this.state = 278; + _localctx._left = this.operatorExpression(0); + this.state = 279; + this.comparisonOperator(); + this.state = 280; + _localctx._right = this.operatorExpression(0); } } catch (re) { @@ -963,57 +1144,45 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public field(): FieldContext { - let _localctx: FieldContext = new FieldContext(this._ctx, this.state); - this.enterRule(_localctx, 26, esql_parser.RULE_field); + public mathFn(): MathFnContext { + let _localctx: MathFnContext = new MathFnContext(this._ctx, this.state); + this.enterRule(_localctx, 26, esql_parser.RULE_mathFn); + let _la: number; try { - this.state = 197; + this.enterOuterAlt(_localctx, 1); + { + this.state = 282; + this.functionIdentifier(); + this.state = 283; + this.match(esql_parser.LP); + this.state = 292; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 16, this._ctx) ) { - case 1: - this.enterOuterAlt(_localctx, 1); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << esql_parser.STRING) | (1 << esql_parser.INTEGER_LITERAL) | (1 << esql_parser.DECIMAL_LITERAL))) !== 0) || ((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & ((1 << (esql_parser.ASTERISK - 53)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 53)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 53)))) !== 0)) { { - this.state = 192; - this.booleanExpression(0); + this.state = 284; + this.functionExpressionArgument(); + this.state = 289; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === esql_parser.COMMA) { + { + { + this.state = 285; + this.match(esql_parser.COMMA); + this.state = 286; + this.functionExpressionArgument(); + } + } + this.state = 291; + this._errHandler.sync(this); + _la = this._input.LA(1); } - break; - - case 2: - this.enterOuterAlt(_localctx, 2); - { - this.state = 193; - this.userVariable(); - this.state = 194; - this.match(esql_parser.ASSIGN); - this.state = 195; - this.booleanExpression(0); } - break; - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public userVariable(): UserVariableContext { - let _localctx: UserVariableContext = new UserVariableContext(this._ctx, this.state); - this.enterRule(_localctx, 28, esql_parser.RULE_userVariable); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 199; - this.identifier(); + + this.state = 294; + this.match(esql_parser.RP); } } catch (re) { @@ -1031,35 +1200,45 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public fromCommand(): FromCommandContext { - let _localctx: FromCommandContext = new FromCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 30, esql_parser.RULE_fromCommand); + public mathEvalFn(): MathEvalFnContext { + let _localctx: MathEvalFnContext = new MathEvalFnContext(this._ctx, this.state); + this.enterRule(_localctx, 28, esql_parser.RULE_mathEvalFn); + let _la: number; try { - let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 201; - this.match(esql_parser.FROM); - this.state = 202; - this.sourceIdentifier(); - this.state = 207; + this.state = 296; + this.mathFunctionIdentifier(); + this.state = 297; + this.match(esql_parser.LP); + this.state = 306; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 17, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << esql_parser.STRING) | (1 << esql_parser.INTEGER_LITERAL) | (1 << esql_parser.DECIMAL_LITERAL))) !== 0) || ((((_la - 34)) & ~0x1F) === 0 && ((1 << (_la - 34)) & ((1 << (esql_parser.LP - 34)) | (1 << (esql_parser.OPENING_BRACKET - 34)) | (1 << (esql_parser.NULL - 34)) | (1 << (esql_parser.BOOLEAN_VALUE - 34)) | (1 << (esql_parser.PLUS - 34)) | (1 << (esql_parser.MINUS - 34)) | (1 << (esql_parser.ASTERISK - 34)) | (1 << (esql_parser.MATH_FUNCTION - 34)) | (1 << (esql_parser.UNARY_FUNCTION - 34)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 34)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 34)))) !== 0)) { + { + this.state = 298; + this.mathFunctionExpressionArgument(); + this.state = 303; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === esql_parser.COMMA) { { { - this.state = 203; + this.state = 299; this.match(esql_parser.COMMA); - this.state = 204; - this.sourceIdentifier(); + this.state = 300; + this.mathFunctionExpressionArgument(); } } + this.state = 305; + this._errHandler.sync(this); + _la = this._input.LA(1); + } } - this.state = 209; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 17, this._ctx); } + + this.state = 308; + this.match(esql_parser.RP); } } catch (re) { @@ -1076,55 +1255,152 @@ export class esql_parser extends Parser { } return _localctx; } + + public operatorExpression(): OperatorExpressionContext; + public operatorExpression(_p: number): OperatorExpressionContext; // @RuleVersion(0) - public evalCommand(): EvalCommandContext { - let _localctx: EvalCommandContext = new EvalCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 32, esql_parser.RULE_evalCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 210; - this.match(esql_parser.EVAL); - this.state = 211; - this.fields(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); + public operatorExpression(_p?: number): OperatorExpressionContext { + if (_p === undefined) { + _p = 0; } - return _localctx; - } - // @RuleVersion(0) - public statsCommand(): StatsCommandContext { - let _localctx: StatsCommandContext = new StatsCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 34, esql_parser.RULE_statsCommand); + + let _parentctx: ParserRuleContext = this._ctx; + let _parentState: number = this.state; + let _localctx: OperatorExpressionContext = new OperatorExpressionContext(this._ctx, _parentState); + let _prevctx: OperatorExpressionContext = _localctx; + let _startState: number = 30; + this.enterRecursionRule(_localctx, 30, esql_parser.RULE_operatorExpression, _p); + let _la: number; try { + let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 213; - this.match(esql_parser.STATS); - this.state = 214; - this.fields(); - this.state = 217; + this.state = 316; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 18, this._ctx) ) { - case 1: + switch (this._input.LA(1)) { + case esql_parser.STRING: + case esql_parser.INTEGER_LITERAL: + case esql_parser.DECIMAL_LITERAL: + case esql_parser.LP: + case esql_parser.OPENING_BRACKET: + case esql_parser.NULL: + case esql_parser.BOOLEAN_VALUE: + case esql_parser.ASTERISK: + case esql_parser.UNQUOTED_IDENTIFIER: + case esql_parser.QUOTED_IDENTIFIER: { - this.state = 215; - this.match(esql_parser.BY); - this.state = 216; - this.qualifiedNames(); + this.state = 311; + this.primaryExpression(); + } + break; + case esql_parser.UNARY_FUNCTION: + { + this.state = 312; + this.mathFn(); } break; + case esql_parser.MATH_FUNCTION: + { + this.state = 313; + this.mathEvalFn(); + } + break; + case esql_parser.PLUS: + case esql_parser.MINUS: + { + this.state = 314; + _localctx._operator = this._input.LT(1); + _la = this._input.LA(1); + if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { + _localctx._operator = this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 315; + this.operatorExpression(3); + } + break; + default: + throw new NoViableAltException(this); + } + this._ctx._stop = this._input.tryLT(-1); + this.state = 326; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 29, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + if (this._parseListeners != null) { + this.triggerExitRuleEvent(); + } + _prevctx = _localctx; + { + this.state = 324; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 28, this._ctx) ) { + case 1: + { + _localctx = new OperatorExpressionContext(_parentctx, _parentState); + _localctx._left = _prevctx; + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_operatorExpression); + this.state = 318; + if (!(this.precpred(this._ctx, 2))) { + throw new FailedPredicateException(this, "this.precpred(this._ctx, 2)"); + } + this.state = 319; + _localctx._operator = this._input.LT(1); + _la = this._input.LA(1); + if (!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & ((1 << (esql_parser.ASTERISK - 53)) | (1 << (esql_parser.SLASH - 53)) | (1 << (esql_parser.PERCENT - 53)))) !== 0))) { + _localctx._operator = this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 320; + _localctx._right = this.operatorExpression(3); + } + break; + + case 2: + { + _localctx = new OperatorExpressionContext(_parentctx, _parentState); + _localctx._left = _prevctx; + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_operatorExpression); + this.state = 321; + if (!(this.precpred(this._ctx, 1))) { + throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); + } + this.state = 322; + _localctx._operator = this._input.LT(1); + _la = this._input.LA(1); + if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { + _localctx._operator = this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 323; + _localctx._right = this.operatorExpression(2); + } + break; + } + } + } + this.state = 328; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 29, this._ctx); } } } @@ -1138,30 +1414,84 @@ export class esql_parser extends Parser { } } finally { - this.exitRule(); + this.unrollRecursionContexts(_parentctx); } return _localctx; } // @RuleVersion(0) - public sourceIdentifier(): SourceIdentifierContext { - let _localctx: SourceIdentifierContext = new SourceIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 36, esql_parser.RULE_sourceIdentifier); + public primaryExpression(): PrimaryExpressionContext { + let _localctx: PrimaryExpressionContext = new PrimaryExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 32, esql_parser.RULE_primaryExpression); let _la: number; try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 219; - _la = this._input.LA(1); - if (!(_la === esql_parser.SRC_UNQUOTED_IDENTIFIER || _la === esql_parser.SRC_QUOTED_IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; + this.state = 349; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 32, this._ctx) ) { + case 1: + this.enterOuterAlt(_localctx, 1); + { + this.state = 329; + this.constant(); } + break; - this._errHandler.reportMatch(this); - this.consume(); - } + case 2: + this.enterOuterAlt(_localctx, 2); + { + this.state = 330; + this.qualifiedName(); + } + break; + + case 3: + this.enterOuterAlt(_localctx, 3); + { + this.state = 331; + this.match(esql_parser.LP); + this.state = 332; + this.booleanExpression(0); + this.state = 333; + this.match(esql_parser.RP); + } + break; + + case 4: + this.enterOuterAlt(_localctx, 4); + { + this.state = 335; + this.identifier(); + this.state = 336; + this.match(esql_parser.LP); + this.state = 345; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << esql_parser.STRING) | (1 << esql_parser.INTEGER_LITERAL) | (1 << esql_parser.DECIMAL_LITERAL))) !== 0) || ((((_la - 34)) & ~0x1F) === 0 && ((1 << (_la - 34)) & ((1 << (esql_parser.LP - 34)) | (1 << (esql_parser.OPENING_BRACKET - 34)) | (1 << (esql_parser.NOT - 34)) | (1 << (esql_parser.NULL - 34)) | (1 << (esql_parser.BOOLEAN_VALUE - 34)) | (1 << (esql_parser.PLUS - 34)) | (1 << (esql_parser.MINUS - 34)) | (1 << (esql_parser.ASTERISK - 34)) | (1 << (esql_parser.MATH_FUNCTION - 34)) | (1 << (esql_parser.UNARY_FUNCTION - 34)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 34)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 34)))) !== 0)) { + { + this.state = 337; + this.booleanExpression(0); + this.state = 342; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === esql_parser.COMMA) { + { + { + this.state = 338; + this.match(esql_parser.COMMA); + this.state = 339; + this.booleanExpression(0); + } + } + this.state = 344; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + this.state = 347; + this.match(esql_parser.RP); + } + break; } } catch (re) { @@ -1179,30 +1509,16 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public functionExpressionArgument(): FunctionExpressionArgumentContext { - let _localctx: FunctionExpressionArgumentContext = new FunctionExpressionArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 38, esql_parser.RULE_functionExpressionArgument); + public rowCommand(): RowCommandContext { + let _localctx: RowCommandContext = new RowCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 34, esql_parser.RULE_rowCommand); try { - this.state = 223; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.UNQUOTED_IDENTIFIER: - case esql_parser.QUOTED_IDENTIFIER: - this.enterOuterAlt(_localctx, 1); - { - this.state = 221; - this.qualifiedName(); - } - break; - case esql_parser.STRING: - this.enterOuterAlt(_localctx, 2); - { - this.state = 222; - this.string(); - } - break; - default: - throw new NoViableAltException(this); + this.enterOuterAlt(_localctx, 1); + { + this.state = 351; + this.match(esql_parser.ROW); + this.state = 352; + this.fields(); } } catch (re) { @@ -1220,32 +1536,32 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public qualifiedName(): QualifiedNameContext { - let _localctx: QualifiedNameContext = new QualifiedNameContext(this._ctx, this.state); - this.enterRule(_localctx, 40, esql_parser.RULE_qualifiedName); + public fields(): FieldsContext { + let _localctx: FieldsContext = new FieldsContext(this._ctx, this.state); + this.enterRule(_localctx, 36, esql_parser.RULE_fields); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 225; - this.identifier(); - this.state = 230; + this.state = 354; + this.field(); + this.state = 359; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 33, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 226; - this.match(esql_parser.DOT); - this.state = 227; - this.identifier(); + this.state = 355; + this.match(esql_parser.COMMA); + this.state = 356; + this.field(); } } } - this.state = 232; + this.state = 361; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 33, this._ctx); } } } @@ -1264,33 +1580,32 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public qualifiedNames(): QualifiedNamesContext { - let _localctx: QualifiedNamesContext = new QualifiedNamesContext(this._ctx, this.state); - this.enterRule(_localctx, 42, esql_parser.RULE_qualifiedNames); + public field(): FieldContext { + let _localctx: FieldContext = new FieldContext(this._ctx, this.state); + this.enterRule(_localctx, 38, esql_parser.RULE_field); try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 233; - this.qualifiedName(); - this.state = 238; + this.state = 367; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 21, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 234; - this.match(esql_parser.COMMA); - this.state = 235; - this.qualifiedName(); - } - } + switch ( this.interpreter.adaptivePredict(this._input, 34, this._ctx) ) { + case 1: + this.enterOuterAlt(_localctx, 1); + { + this.state = 362; + this.booleanExpression(0); } - this.state = 240; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 21, this._ctx); - } + break; + + case 2: + this.enterOuterAlt(_localctx, 2); + { + this.state = 363; + this.userVariable(); + this.state = 364; + this.match(esql_parser.ASSIGN); + this.state = 365; + this.booleanExpression(0); + } + break; } } catch (re) { @@ -1308,16 +1623,16 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public identifier(): IdentifierContext { - let _localctx: IdentifierContext = new IdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 44, esql_parser.RULE_identifier); + public enrichFieldIdentifier(): EnrichFieldIdentifierContext { + let _localctx: EnrichFieldIdentifierContext = new EnrichFieldIdentifierContext(this._ctx, this.state); + this.enterRule(_localctx, 40, esql_parser.RULE_enrichFieldIdentifier); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 241; + this.state = 369; _la = this._input.LA(1); - if (!(_la === esql_parser.UNQUOTED_IDENTIFIER || _la === esql_parser.QUOTED_IDENTIFIER)) { + if (!(_la === esql_parser.ENR_UNQUOTED_IDENTIFIER || _la === esql_parser.ENR_QUOTED_IDENTIFIER)) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -1344,14 +1659,14 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public functionIdentifier(): FunctionIdentifierContext { - let _localctx: FunctionIdentifierContext = new FunctionIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 46, esql_parser.RULE_functionIdentifier); + public userVariable(): UserVariableContext { + let _localctx: UserVariableContext = new UserVariableContext(this._ctx, this.state); + this.enterRule(_localctx, 42, esql_parser.RULE_userVariable); try { this.enterOuterAlt(_localctx, 1); { - this.state = 243; - this.match(esql_parser.UNARY_FUNCTION); + this.state = 371; + this.identifier(); } } catch (re) { @@ -1369,48 +1684,45 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public constant(): ConstantContext { - let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); - this.enterRule(_localctx, 48, esql_parser.RULE_constant); + public fromCommand(): FromCommandContext { + let _localctx: FromCommandContext = new FromCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 44, esql_parser.RULE_fromCommand); try { - this.state = 249; + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 373; + this.match(esql_parser.FROM); + this.state = 374; + this.sourceIdentifier(); + this.state = 379; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.NULL: - _localctx = new NullLiteralContext(_localctx); - this.enterOuterAlt(_localctx, 1); - { - this.state = 245; - this.match(esql_parser.NULL); - } - break; - case esql_parser.INTEGER_LITERAL: - case esql_parser.DECIMAL_LITERAL: - _localctx = new NumericLiteralContext(_localctx); - this.enterOuterAlt(_localctx, 2); - { - this.state = 246; - this.number(); - } - break; - case esql_parser.BOOLEAN_VALUE: - _localctx = new BooleanLiteralContext(_localctx); - this.enterOuterAlt(_localctx, 3); - { - this.state = 247; - this.booleanValue(); + _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 375; + this.match(esql_parser.COMMA); + this.state = 376; + this.sourceIdentifier(); + } + } } - break; - case esql_parser.STRING: - _localctx = new StringLiteralContext(_localctx); - this.enterOuterAlt(_localctx, 4); + this.state = 381; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + } + this.state = 383; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 36, this._ctx) ) { + case 1: { - this.state = 248; - this.string(); + this.state = 382; + this.metadata(); } break; - default: - throw new NoViableAltException(this); + } } } catch (re) { @@ -1428,16 +1740,37 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public limitCommand(): LimitCommandContext { - let _localctx: LimitCommandContext = new LimitCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 50, esql_parser.RULE_limitCommand); + public metadata(): MetadataContext { + let _localctx: MetadataContext = new MetadataContext(this._ctx, this.state); + this.enterRule(_localctx, 46, esql_parser.RULE_metadata); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 251; - this.match(esql_parser.LIMIT); - this.state = 252; - this.match(esql_parser.INTEGER_LITERAL); + this.state = 385; + this.match(esql_parser.OPENING_BRACKET); + this.state = 386; + this.match(esql_parser.METADATA); + this.state = 387; + this.sourceIdentifier(); + this.state = 392; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === esql_parser.COMMA) { + { + { + this.state = 388; + this.match(esql_parser.COMMA); + this.state = 389; + this.sourceIdentifier(); + } + } + this.state = 394; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 395; + this.match(esql_parser.CLOSING_BRACKET); } } catch (re) { @@ -1455,35 +1788,16 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public sortCommand(): SortCommandContext { - let _localctx: SortCommandContext = new SortCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 52, esql_parser.RULE_sortCommand); + public evalCommand(): EvalCommandContext { + let _localctx: EvalCommandContext = new EvalCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 48, esql_parser.RULE_evalCommand); try { - let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 254; - this.match(esql_parser.SORT); - this.state = 255; - this.orderExpression(); - this.state = 260; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 23, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 256; - this.match(esql_parser.COMMA); - this.state = 257; - this.orderExpression(); - } - } - } - this.state = 262; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 23, this._ctx); - } + this.state = 397; + this.match(esql_parser.EVAL); + this.state = 398; + this.fields(); } } catch (re) { @@ -1501,35 +1815,33 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public orderExpression(): OrderExpressionContext { - let _localctx: OrderExpressionContext = new OrderExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 54, esql_parser.RULE_orderExpression); + public statsCommand(): StatsCommandContext { + let _localctx: StatsCommandContext = new StatsCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 50, esql_parser.RULE_statsCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 263; - this.booleanExpression(0); - this.state = 265; + this.state = 400; + this.match(esql_parser.STATS); + this.state = 402; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 24, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 38, this._ctx) ) { case 1: { - this.state = 264; - this.match(esql_parser.ORDERING); + this.state = 401; + this.fields(); } break; } - this.state = 269; + this.state = 406; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 25, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 39, this._ctx) ) { case 1: { - this.state = 267; - this.match(esql_parser.NULLS_ORDERING); - { - this.state = 268; - this.match(esql_parser.NULLS_ORDERING_DIRECTION); - } + this.state = 404; + this.match(esql_parser.BY); + this.state = 405; + this.qualifiedNames(); } break; } @@ -1550,34 +1862,24 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public projectCommand(): ProjectCommandContext { - let _localctx: ProjectCommandContext = new ProjectCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 56, esql_parser.RULE_projectCommand); + public sourceIdentifier(): SourceIdentifierContext { + let _localctx: SourceIdentifierContext = new SourceIdentifierContext(this._ctx, this.state); + this.enterRule(_localctx, 52, esql_parser.RULE_sourceIdentifier); + let _la: number; try { - let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 271; - this.match(esql_parser.PROJECT); - this.state = 272; - this.projectClause(); - this.state = 277; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 26, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 273; - this.match(esql_parser.COMMA); - this.state = 274; - this.projectClause(); - } - } + this.state = 408; + _la = this._input.LA(1); + if (!(_la === esql_parser.SRC_UNQUOTED_IDENTIFIER || _la === esql_parser.SRC_QUOTED_IDENTIFIER)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; } - this.state = 279; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 26, this._ctx); + + this._errHandler.reportMatch(this); + this.consume(); } } } @@ -1596,32 +1898,25 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public projectClause(): ProjectClauseContext { - let _localctx: ProjectClauseContext = new ProjectClauseContext(this._ctx, this.state); - this.enterRule(_localctx, 58, esql_parser.RULE_projectClause); + public enrichIdentifier(): EnrichIdentifierContext { + let _localctx: EnrichIdentifierContext = new EnrichIdentifierContext(this._ctx, this.state); + this.enterRule(_localctx, 54, esql_parser.RULE_enrichIdentifier); + let _la: number; try { - this.state = 285; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 27, this._ctx) ) { - case 1: - this.enterOuterAlt(_localctx, 1); - { - this.state = 280; - this.sourceIdentifier(); + this.enterOuterAlt(_localctx, 1); + { + this.state = 410; + _la = this._input.LA(1); + if (!(_la === esql_parser.ENR_UNQUOTED_IDENTIFIER || _la === esql_parser.ENR_QUOTED_IDENTIFIER)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; } - break; - case 2: - this.enterOuterAlt(_localctx, 2); - { - this.state = 281; - _localctx._newName = this.sourceIdentifier(); - this.state = 282; - this.match(esql_parser.ASSIGN); - this.state = 283; - _localctx._oldName = this.sourceIdentifier(); - } - break; + this._errHandler.reportMatch(this); + this.consume(); + } } } catch (re) { @@ -1639,14 +1934,39 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public booleanValue(): BooleanValueContext { - let _localctx: BooleanValueContext = new BooleanValueContext(this._ctx, this.state); - this.enterRule(_localctx, 60, esql_parser.RULE_booleanValue); + public functionExpressionArgument(): FunctionExpressionArgumentContext { + let _localctx: FunctionExpressionArgumentContext = new FunctionExpressionArgumentContext(this._ctx, this.state); + this.enterRule(_localctx, 56, esql_parser.RULE_functionExpressionArgument); try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 287; - this.match(esql_parser.BOOLEAN_VALUE); + this.state = 415; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case esql_parser.ASTERISK: + case esql_parser.UNQUOTED_IDENTIFIER: + case esql_parser.QUOTED_IDENTIFIER: + this.enterOuterAlt(_localctx, 1); + { + this.state = 412; + this.qualifiedName(); + } + break; + case esql_parser.STRING: + this.enterOuterAlt(_localctx, 2); + { + this.state = 413; + this.string(); + } + break; + case esql_parser.INTEGER_LITERAL: + case esql_parser.DECIMAL_LITERAL: + this.enterOuterAlt(_localctx, 3); + { + this.state = 414; + this.number(); + } + break; + default: + throw new NoViableAltException(this); } } catch (re) { @@ -1664,31 +1984,64 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public number(): NumberContext { - let _localctx: NumberContext = new NumberContext(this._ctx, this.state); - this.enterRule(_localctx, 62, esql_parser.RULE_number); + public mathFunctionExpressionArgument(): MathFunctionExpressionArgumentContext { + let _localctx: MathFunctionExpressionArgumentContext = new MathFunctionExpressionArgumentContext(this._ctx, this.state); + this.enterRule(_localctx, 58, esql_parser.RULE_mathFunctionExpressionArgument); try { - this.state = 291; + this.state = 425; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.DECIMAL_LITERAL: - _localctx = new DecimalLiteralContext(_localctx); + switch ( this.interpreter.adaptivePredict(this._input, 41, this._ctx) ) { + case 1: this.enterOuterAlt(_localctx, 1); { - this.state = 289; - this.match(esql_parser.DECIMAL_LITERAL); + this.state = 417; + this.qualifiedName(); } break; - case esql_parser.INTEGER_LITERAL: - _localctx = new IntegerLiteralContext(_localctx); + + case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 290; - this.match(esql_parser.INTEGER_LITERAL); + this.state = 418; + this.string(); + } + break; + + case 3: + this.enterOuterAlt(_localctx, 3); + { + this.state = 419; + this.number(); + } + break; + + case 4: + this.enterOuterAlt(_localctx, 4); + { + this.state = 420; + this.operatorExpression(0); + } + break; + + case 5: + this.enterOuterAlt(_localctx, 5); + { + this.state = 421; + this.number(); + { + this.state = 422; + this.match(esql_parser.DATE_LITERAL); + } + } + break; + + case 6: + this.enterOuterAlt(_localctx, 6); + { + this.state = 424; + this.comparison(); } break; - default: - throw new NoViableAltException(this); } } catch (re) { @@ -1706,14 +2059,33 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public string(): StringContext { - let _localctx: StringContext = new StringContext(this._ctx, this.state); - this.enterRule(_localctx, 64, esql_parser.RULE_string); + public qualifiedName(): QualifiedNameContext { + let _localctx: QualifiedNameContext = new QualifiedNameContext(this._ctx, this.state); + this.enterRule(_localctx, 60, esql_parser.RULE_qualifiedName); try { + let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 293; - this.match(esql_parser.STRING); + this.state = 427; + this.identifier(); + this.state = 432; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 42, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 428; + this.match(esql_parser.DOT); + this.state = 429; + this.identifier(); + } + } + } + this.state = 434; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 42, this._ctx); + } } } catch (re) { @@ -1731,14 +2103,33 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public comparisonOperator(): ComparisonOperatorContext { - let _localctx: ComparisonOperatorContext = new ComparisonOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 66, esql_parser.RULE_comparisonOperator); + public qualifiedNames(): QualifiedNamesContext { + let _localctx: QualifiedNamesContext = new QualifiedNamesContext(this._ctx, this.state); + this.enterRule(_localctx, 62, esql_parser.RULE_qualifiedNames); try { + let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 295; - this.match(esql_parser.COMPARISON_OPERATOR); + this.state = 435; + this.qualifiedName(); + this.state = 440; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 43, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 436; + this.match(esql_parser.COMMA); + this.state = 437; + this.qualifiedName(); + } + } + } + this.state = 442; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 43, this._ctx); + } } } catch (re) { @@ -1756,16 +2147,25 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public explainCommand(): ExplainCommandContext { - let _localctx: ExplainCommandContext = new ExplainCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 68, esql_parser.RULE_explainCommand); + public identifier(): IdentifierContext { + let _localctx: IdentifierContext = new IdentifierContext(this._ctx, this.state); + this.enterRule(_localctx, 64, esql_parser.RULE_identifier); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 297; - this.match(esql_parser.EXPLAIN); - this.state = 298; - this.subqueryExpression(); + this.state = 443; + _la = this._input.LA(1); + if (!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & ((1 << (esql_parser.ASTERISK - 53)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 53)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 53)))) !== 0))) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } } } catch (re) { @@ -1783,18 +2183,14 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public subqueryExpression(): SubqueryExpressionContext { - let _localctx: SubqueryExpressionContext = new SubqueryExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 70, esql_parser.RULE_subqueryExpression); + public mathFunctionIdentifier(): MathFunctionIdentifierContext { + let _localctx: MathFunctionIdentifierContext = new MathFunctionIdentifierContext(this._ctx, this.state); + this.enterRule(_localctx, 66, esql_parser.RULE_mathFunctionIdentifier); try { this.enterOuterAlt(_localctx, 1); { - this.state = 300; - this.match(esql_parser.OPENING_BRACKET); - this.state = 301; - this.query(0); - this.state = 302; - this.match(esql_parser.CLOSING_BRACKET); + this.state = 445; + this.match(esql_parser.MATH_FUNCTION); } } catch (re) { @@ -1811,488 +2207,2199 @@ export class esql_parser extends Parser { } return _localctx; } - - public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 1: - return this.query_sempred(_localctx as QueryContext, predIndex); - - case 5: - return this.booleanExpression_sempred(_localctx as BooleanExpressionContext, predIndex); - - case 9: - return this.operatorExpression_sempred(_localctx as OperatorExpressionContext, predIndex); - } - return true; - } - private query_sempred(_localctx: QueryContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return this.precpred(this._ctx, 1); + // @RuleVersion(0) + public functionIdentifier(): FunctionIdentifierContext { + let _localctx: FunctionIdentifierContext = new FunctionIdentifierContext(this._ctx, this.state); + this.enterRule(_localctx, 68, esql_parser.RULE_functionIdentifier); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 447; + this.match(esql_parser.UNARY_FUNCTION); + } } - return true; - } - private booleanExpression_sempred(_localctx: BooleanExpressionContext, predIndex: number): boolean { - switch (predIndex) { - case 1: - return this.precpred(this._ctx, 2); - - case 2: - return this.precpred(this._ctx, 1); + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } } - return true; - } - private operatorExpression_sempred(_localctx: OperatorExpressionContext, predIndex: number): boolean { - switch (predIndex) { - case 3: - return this.precpred(this._ctx, 2); - - case 4: - return this.precpred(this._ctx, 1); + finally { + this.exitRule(); } - return true; + return _localctx; } + // @RuleVersion(0) + public constant(): ConstantContext { + let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); + this.enterRule(_localctx, 70, esql_parser.RULE_constant); + let _la: number; + try { + this.state = 486; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 47, this._ctx) ) { + case 1: + this.enterOuterAlt(_localctx, 1); + { + this.state = 449; + this.match(esql_parser.NULL); + } + break; - public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x033\u0133\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + - "\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t\x17\x04" + - "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + - "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + - "\t#\x04$\t$\x04%\t%\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03" + - "\x03\x03\x03\x03\x03\x07\x03T\n\x03\f\x03\x0E\x03W\v\x03\x03\x04\x03\x04" + - "\x03\x04\x05\x04\\\n\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05" + - "\x05\x05d\n\x05\x03\x06\x03\x06\x03\x06\x03\x07\x03\x07\x03\x07\x03\x07" + - "\x05\x07m\n\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x07\x07" + - "u\n\x07\f\x07\x0E\x07x\v\x07\x03\b\x03\b\x05\b|\n\b\x03\t\x03\t\x03\t" + - "\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x07\n\x87\n\n\f\n\x0E\n\x8A\v\n\x05" + - "\n\x8C\n\n\x03\n\x03\n\x03\v\x03\v\x03\v\x03\v\x03\v\x05\v\x95\n\v\x03" + - "\v\x03\v\x03\v\x03\v\x03\v\x03\v\x07\v\x9D\n\v\f\v\x0E\v\xA0\v\v\x03\f" + - "\x03\f\x03\f\x03\f\x03\f\x03\f\x03\f\x03\f\x03\f\x03\f\x03\f\x07\f\xAD" + - "\n\f\f\f\x0E\f\xB0\v\f\x05\f\xB2\n\f\x03\f\x03\f\x05\f\xB6\n\f\x03\r\x03" + - "\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x07\x0E\xBE\n\x0E\f\x0E\x0E\x0E\xC1\v" + - "\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x05\x0F\xC8\n\x0F\x03\x10" + - "\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x07\x11\xD0\n\x11\f\x11\x0E\x11" + - "\xD3\v\x11\x03\x12\x03\x12\x03\x12\x03\x13\x03\x13\x03\x13\x03\x13\x05" + - "\x13\xDC\n\x13\x03\x14\x03\x14\x03\x15\x03\x15\x05\x15\xE2\n\x15\x03\x16" + - "\x03\x16\x03\x16\x07\x16\xE7\n\x16\f\x16\x0E\x16\xEA\v\x16\x03\x17\x03" + - "\x17\x03\x17\x07\x17\xEF\n\x17\f\x17\x0E\x17\xF2\v\x17\x03\x18\x03\x18" + - "\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x05\x1A\xFC\n\x1A\x03" + - "\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u0105\n\x1C" + - "\f\x1C\x0E\x1C\u0108\v\x1C\x03\x1D\x03\x1D\x05\x1D\u010C\n\x1D\x03\x1D" + - "\x03\x1D\x05\x1D\u0110\n\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x07\x1E\u0116" + - "\n\x1E\f\x1E\x0E\x1E\u0119\v\x1E\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F" + - "\x05\x1F\u0120\n\x1F\x03 \x03 \x03!\x03!\x05!\u0126\n!\x03\"\x03\"\x03" + - "#\x03#\x03$\x03$\x03$\x03%\x03%\x03%\x03%\x03%\x02\x02\x05\x04\f\x14&" + - "\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14" + - "\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&\x02(\x02" + - "*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02B\x02D\x02" + - "F\x02H\x02\x02\x06\x03\x02!\"\x03\x02#%\x03\x02/0\x03\x02*+\x02\u0135" + - "\x02J\x03\x02\x02\x02\x04M\x03\x02\x02\x02\x06[\x03\x02\x02\x02\bc\x03" + - "\x02\x02\x02\ne\x03\x02\x02\x02\fl\x03\x02\x02\x02\x0E{\x03\x02\x02\x02" + - "\x10}\x03\x02\x02\x02\x12\x81\x03\x02\x02\x02\x14\x94\x03\x02\x02\x02" + - "\x16\xB5\x03\x02\x02\x02\x18\xB7\x03\x02\x02\x02\x1A\xBA\x03\x02\x02\x02" + - "\x1C\xC7\x03\x02\x02\x02\x1E\xC9\x03\x02\x02\x02 \xCB\x03\x02\x02\x02" + - "\"\xD4\x03\x02\x02\x02$\xD7\x03\x02\x02\x02&\xDD\x03\x02\x02\x02(\xE1" + - "\x03\x02\x02\x02*\xE3\x03\x02\x02\x02,\xEB\x03\x02\x02\x02.\xF3\x03\x02" + - "\x02\x020\xF5\x03\x02\x02\x022\xFB\x03\x02\x02\x024\xFD\x03\x02\x02\x02" + - "6\u0100\x03\x02\x02\x028\u0109\x03\x02\x02\x02:\u0111\x03\x02\x02\x02" + - "<\u011F\x03\x02\x02\x02>\u0121\x03\x02\x02\x02@\u0125\x03\x02\x02\x02" + - "B\u0127\x03\x02\x02\x02D\u0129\x03\x02\x02\x02F\u012B\x03\x02\x02\x02" + - "H\u012E\x03\x02\x02\x02JK\x05\x04\x03\x02KL\x07\x02\x02\x03L\x03\x03\x02" + - "\x02\x02MN\b\x03\x01\x02NO\x05\x06\x04\x02OU\x03\x02\x02\x02PQ\f\x03\x02" + - "\x02QR\x07\x0F\x02\x02RT\x05\b\x05\x02SP\x03\x02\x02\x02TW\x03\x02\x02" + - "\x02US\x03\x02\x02\x02UV\x03\x02\x02\x02V\x05\x03\x02\x02\x02WU\x03\x02" + - "\x02\x02X\\\x05F$\x02Y\\\x05 \x11\x02Z\\\x05\x18\r\x02[X\x03\x02\x02\x02" + - "[Y\x03\x02\x02\x02[Z\x03\x02\x02\x02\\\x07\x03\x02\x02\x02]d\x05\"\x12" + - "\x02^d\x054\x1B\x02_d\x05:\x1E\x02`d\x056\x1C\x02ad\x05$\x13\x02bd\x05" + - "\n\x06\x02c]\x03\x02\x02\x02c^\x03\x02\x02\x02c_\x03\x02\x02\x02c`\x03" + - "\x02\x02\x02ca\x03\x02\x02\x02cb\x03\x02\x02\x02d\t\x03\x02\x02\x02ef" + - "\x07\b\x02\x02fg\x05\f\x07\x02g\v\x03\x02\x02\x02hi\b\x07\x01\x02ij\x07" + - "\x1B\x02\x02jm\x05\f\x07\x06km\x05\x0E\b\x02lh\x03\x02\x02\x02lk\x03\x02" + - "\x02\x02mv\x03\x02\x02\x02no\f\x04\x02\x02op\x07\x14\x02\x02pu\x05\f\x07" + - "\x05qr\f\x03\x02\x02rs\x07\x1D\x02\x02su\x05\f\x07\x04tn\x03\x02\x02\x02" + - "tq\x03\x02\x02\x02ux\x03\x02\x02\x02vt\x03\x02\x02\x02vw\x03\x02\x02\x02" + - "w\r\x03\x02\x02\x02xv\x03\x02\x02\x02y|\x05\x14\v\x02z|\x05\x10\t\x02" + - "{y\x03\x02\x02\x02{z\x03\x02\x02\x02|\x0F\x03\x02\x02\x02}~\x05\x14\v" + - "\x02~\x7F\x05D#\x02\x7F\x80\x05\x14\v\x02\x80\x11\x03\x02\x02\x02\x81" + - "\x82\x050\x19\x02\x82\x8B\x07\x18\x02\x02\x83\x88\x05(\x15\x02\x84\x85" + - "\x07\x16\x02\x02\x85\x87\x05(\x15\x02\x86\x84\x03\x02\x02\x02\x87\x8A" + - "\x03\x02\x02\x02\x88\x86\x03\x02\x02\x02\x88\x89\x03\x02\x02\x02\x89\x8C" + - "\x03\x02\x02\x02\x8A\x88\x03\x02\x02\x02\x8B\x83\x03\x02\x02\x02\x8B\x8C" + - "\x03\x02\x02\x02\x8C\x8D\x03\x02\x02\x02\x8D\x8E\x07\x1E\x02\x02\x8E\x13" + - "\x03\x02\x02\x02\x8F\x90\b\v\x01\x02\x90\x95\x05\x16\f\x02\x91\x95\x05" + - "\x12\n\x02\x92\x93\t\x02\x02\x02\x93\x95\x05\x14\v\x05\x94\x8F\x03\x02" + - "\x02\x02\x94\x91\x03\x02\x02\x02\x94\x92\x03\x02\x02\x02\x95\x9E\x03\x02" + - "\x02\x02\x96\x97\f\x04\x02\x02\x97\x98\t\x03\x02\x02\x98\x9D\x05\x14\v" + - "\x05\x99\x9A\f\x03\x02\x02\x9A\x9B\t\x02\x02\x02\x9B\x9D\x05\x14\v\x04" + - "\x9C\x96\x03\x02\x02\x02\x9C\x99\x03\x02\x02\x02\x9D\xA0\x03\x02\x02\x02" + - "\x9E\x9C\x03\x02\x02\x02\x9E\x9F\x03\x02\x02\x02\x9F\x15\x03\x02\x02\x02" + - "\xA0\x9E\x03\x02\x02\x02\xA1\xB6\x052\x1A\x02\xA2\xB6\x05*\x16\x02\xA3" + - "\xA4\x07\x18\x02\x02\xA4\xA5\x05\f\x07\x02\xA5\xA6\x07\x1E\x02\x02\xA6" + - "\xB6\x03\x02\x02\x02\xA7\xA8\x05.\x18\x02\xA8\xB1\x07\x18\x02\x02\xA9" + - "\xAE\x05\f\x07\x02\xAA\xAB\x07\x16\x02\x02\xAB\xAD\x05\f\x07\x02\xAC\xAA" + - "\x03\x02\x02\x02\xAD\xB0\x03\x02\x02\x02\xAE\xAC\x03\x02\x02\x02\xAE\xAF" + - "\x03\x02\x02\x02\xAF\xB2\x03\x02\x02\x02\xB0\xAE\x03\x02\x02\x02\xB1\xA9" + - "\x03\x02\x02\x02\xB1\xB2\x03\x02\x02\x02\xB2\xB3\x03\x02\x02\x02\xB3\xB4" + - "\x07\x1E\x02\x02\xB4\xB6\x03\x02\x02\x02\xB5\xA1\x03\x02\x02\x02\xB5\xA2" + - "\x03\x02\x02\x02\xB5\xA3\x03\x02\x02\x02\xB5\xA7\x03\x02\x02\x02\xB6\x17" + - "\x03\x02\x02\x02\xB7\xB8\x07\x06\x02\x02\xB8\xB9\x05\x1A\x0E\x02\xB9\x19" + - "\x03\x02\x02\x02\xBA\xBF\x05\x1C\x0F\x02\xBB\xBC\x07\x16\x02\x02\xBC\xBE" + - "\x05\x1C\x0F\x02\xBD\xBB\x03\x02\x02\x02\xBE\xC1\x03\x02\x02\x02\xBF\xBD" + - "\x03\x02\x02\x02\xBF\xC0\x03\x02\x02\x02\xC0\x1B\x03\x02\x02\x02\xC1\xBF" + - "\x03\x02\x02\x02\xC2\xC8\x05\f\x07\x02\xC3\xC4\x05\x1E\x10\x02\xC4\xC5" + - "\x07\x15\x02\x02\xC5\xC6\x05\f\x07\x02\xC6\xC8\x03\x02\x02\x02\xC7\xC2" + - "\x03\x02\x02\x02\xC7\xC3\x03\x02\x02\x02\xC8\x1D\x03\x02\x02\x02\xC9\xCA" + - "\x05.\x18\x02\xCA\x1F\x03\x02\x02\x02\xCB\xCC\x07\x05\x02\x02\xCC\xD1" + - "\x05&\x14\x02\xCD\xCE\x07\x16\x02\x02\xCE\xD0\x05&\x14\x02\xCF\xCD\x03" + - "\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1\xD2\x03" + - "\x02\x02\x02\xD2!\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4\xD5\x07" + - "\x03\x02\x02\xD5\xD6\x05\x1A\x0E\x02\xD6#\x03\x02\x02\x02\xD7\xD8\x07" + - "\x07\x02\x02\xD8\xDB\x05\x1A\x0E\x02\xD9\xDA\x07\x13\x02\x02\xDA\xDC\x05" + - ",\x17\x02\xDB\xD9\x03\x02\x02\x02\xDB\xDC\x03\x02\x02\x02\xDC%\x03\x02" + - "\x02\x02\xDD\xDE\t\x04\x02\x02\xDE\'\x03\x02\x02\x02\xDF\xE2\x05*\x16" + - "\x02\xE0\xE2\x05B\"\x02\xE1\xDF\x03\x02\x02\x02\xE1\xE0\x03\x02\x02\x02" + - "\xE2)\x03\x02\x02\x02\xE3\xE8\x05.\x18\x02\xE4\xE5\x07\x17\x02\x02\xE5" + - "\xE7\x05.\x18\x02\xE6\xE4\x03\x02\x02\x02\xE7\xEA\x03\x02\x02\x02\xE8" + - "\xE6\x03\x02\x02\x02\xE8\xE9\x03\x02\x02\x02\xE9+\x03\x02\x02\x02\xEA" + - "\xE8\x03\x02\x02\x02\xEB\xF0\x05*\x16\x02\xEC\xED\x07\x16\x02\x02\xED" + - "\xEF\x05*\x16\x02\xEE\xEC\x03\x02\x02\x02\xEF\xF2\x03\x02\x02\x02\xF0" + - "\xEE\x03\x02\x02\x02\xF0\xF1\x03\x02\x02\x02\xF1-\x03\x02\x02\x02\xF2" + - "\xF0\x03\x02\x02\x02\xF3\xF4\t\x05\x02\x02\xF4/\x03\x02\x02\x02\xF5\xF6" + - "\x07)\x02\x02\xF61\x03\x02\x02\x02\xF7\xFC\x07\x1C\x02\x02\xF8\xFC\x05" + - "@!\x02\xF9\xFC\x05> \x02\xFA\xFC\x05B\"\x02\xFB\xF7\x03\x02\x02\x02\xFB" + - "\xF8\x03\x02\x02\x02\xFB\xF9\x03\x02\x02\x02\xFB\xFA\x03\x02\x02\x02\xFC" + - "3\x03\x02\x02\x02\xFD\xFE\x07\n\x02\x02\xFE\xFF\x07\x11\x02\x02\xFF5\x03" + - "\x02\x02\x02\u0100\u0101\x07\t\x02\x02\u0101\u0106\x058\x1D\x02\u0102" + - "\u0103\x07\x16\x02\x02\u0103\u0105\x058\x1D\x02\u0104\u0102\x03\x02\x02" + - "\x02\u0105\u0108\x03\x02\x02\x02\u0106\u0104\x03\x02\x02\x02\u0106\u0107" + - "\x03\x02\x02\x02\u01077\x03\x02\x02\x02\u0108\u0106\x03\x02\x02\x02\u0109" + - "\u010B\x05\f\x07\x02\u010A\u010C\x07&\x02\x02\u010B\u010A\x03\x02\x02" + - "\x02\u010B\u010C\x03\x02\x02\x02\u010C\u010F\x03\x02\x02\x02\u010D\u010E" + - "\x07\'\x02\x02\u010E\u0110\x07(\x02\x02\u010F\u010D\x03\x02\x02\x02\u010F" + - "\u0110\x03\x02\x02\x02\u01109\x03\x02\x02\x02\u0111\u0112\x07\v\x02\x02" + - "\u0112\u0117\x05<\x1F\x02\u0113\u0114\x07\x16\x02\x02\u0114\u0116\x05" + - "<\x1F\x02\u0115\u0113\x03\x02\x02\x02\u0116\u0119\x03\x02\x02\x02\u0117" + - "\u0115\x03\x02\x02\x02\u0117\u0118\x03\x02\x02\x02\u0118;\x03\x02\x02" + - "\x02\u0119\u0117\x03\x02\x02\x02\u011A\u0120\x05&\x14\x02\u011B\u011C" + - "\x05&\x14\x02\u011C\u011D\x07\x15\x02\x02\u011D\u011E\x05&\x14\x02\u011E" + - "\u0120\x03\x02\x02\x02\u011F\u011A\x03\x02\x02\x02\u011F\u011B\x03\x02" + - "\x02\x02\u0120=\x03\x02\x02\x02\u0121\u0122\x07\x1F\x02\x02\u0122?\x03" + - "\x02\x02\x02\u0123\u0126\x07\x12\x02\x02\u0124\u0126\x07\x11\x02\x02\u0125" + - "\u0123\x03\x02\x02\x02\u0125\u0124\x03\x02\x02\x02\u0126A\x03\x02\x02" + - "\x02\u0127\u0128\x07\x10\x02\x02\u0128C\x03\x02\x02\x02\u0129\u012A\x07" + - " \x02\x02\u012AE\x03\x02\x02\x02\u012B\u012C\x07\x04\x02\x02\u012C\u012D" + - "\x05H%\x02\u012DG\x03\x02\x02\x02\u012E\u012F\x07\x19\x02\x02\u012F\u0130" + - "\x05\x04\x03\x02\u0130\u0131\x07\x1A\x02\x02\u0131I\x03\x02\x02\x02\x1F" + - "U[cltv{\x88\x8B\x94\x9C\x9E\xAE\xB1\xB5\xBF\xC7\xD1\xDB\xE1\xE8\xF0\xFB" + - "\u0106\u010B\u010F\u0117\u011F\u0125"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!esql_parser.__ATN) { - esql_parser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(esql_parser._serializedATN)); - } + case 2: + this.enterOuterAlt(_localctx, 2); + { + this.state = 450; + this.numericValue(); + } + break; - return esql_parser.__ATN; - } + case 3: + this.enterOuterAlt(_localctx, 3); + { + this.state = 451; + this.booleanValue(); + } + break; + case 4: + this.enterOuterAlt(_localctx, 4); + { + this.state = 452; + this.string(); + } + break; + + case 5: + this.enterOuterAlt(_localctx, 5); + { + this.state = 453; + this.match(esql_parser.OPENING_BRACKET); + this.state = 454; + this.numericValue(); + this.state = 459; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === esql_parser.COMMA) { + { + { + this.state = 455; + this.match(esql_parser.COMMA); + this.state = 456; + this.numericValue(); + } + } + this.state = 461; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 462; + this.match(esql_parser.CLOSING_BRACKET); + } + break; + + case 6: + this.enterOuterAlt(_localctx, 6); + { + this.state = 464; + this.match(esql_parser.OPENING_BRACKET); + this.state = 465; + this.booleanValue(); + this.state = 470; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === esql_parser.COMMA) { + { + { + this.state = 466; + this.match(esql_parser.COMMA); + this.state = 467; + this.booleanValue(); + } + } + this.state = 472; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 473; + this.match(esql_parser.CLOSING_BRACKET); + } + break; + + case 7: + this.enterOuterAlt(_localctx, 7); + { + this.state = 475; + this.match(esql_parser.OPENING_BRACKET); + this.state = 476; + this.string(); + this.state = 481; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === esql_parser.COMMA) { + { + { + this.state = 477; + this.match(esql_parser.COMMA); + this.state = 478; + this.string(); + } + } + this.state = 483; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 484; + this.match(esql_parser.CLOSING_BRACKET); + } + break; + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public numericValue(): NumericValueContext { + let _localctx: NumericValueContext = new NumericValueContext(this._ctx, this.state); + this.enterRule(_localctx, 72, esql_parser.RULE_numericValue); + try { + this.state = 490; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case esql_parser.DECIMAL_LITERAL: + this.enterOuterAlt(_localctx, 1); + { + this.state = 488; + this.decimalValue(); + } + break; + case esql_parser.INTEGER_LITERAL: + this.enterOuterAlt(_localctx, 2); + { + this.state = 489; + this.integerValue(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public limitCommand(): LimitCommandContext { + let _localctx: LimitCommandContext = new LimitCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 74, esql_parser.RULE_limitCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 492; + this.match(esql_parser.LIMIT); + this.state = 493; + this.match(esql_parser.INTEGER_LITERAL); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public sortCommand(): SortCommandContext { + let _localctx: SortCommandContext = new SortCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 76, esql_parser.RULE_sortCommand); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 495; + this.match(esql_parser.SORT); + this.state = 496; + this.orderExpression(); + this.state = 501; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 49, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 497; + this.match(esql_parser.COMMA); + this.state = 498; + this.orderExpression(); + } + } + } + this.state = 503; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 49, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public orderExpression(): OrderExpressionContext { + let _localctx: OrderExpressionContext = new OrderExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 78, esql_parser.RULE_orderExpression); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 504; + this.booleanExpression(0); + this.state = 506; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 50, this._ctx) ) { + case 1: + { + this.state = 505; + this.match(esql_parser.ORDERING); + } + break; + } + this.state = 510; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 51, this._ctx) ) { + case 1: + { + this.state = 508; + this.match(esql_parser.NULLS_ORDERING); + { + this.state = 509; + this.match(esql_parser.NULLS_ORDERING_DIRECTION); + } + } + break; + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public projectCommand(): ProjectCommandContext { + let _localctx: ProjectCommandContext = new ProjectCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 80, esql_parser.RULE_projectCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 512; + this.match(esql_parser.PROJECT); + this.state = 513; + this.qualifiedNames(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public keepCommand(): KeepCommandContext { + let _localctx: KeepCommandContext = new KeepCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 82, esql_parser.RULE_keepCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 515; + this.match(esql_parser.KEEP); + this.state = 516; + this.qualifiedNames(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public dropCommand(): DropCommandContext { + let _localctx: DropCommandContext = new DropCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 84, esql_parser.RULE_dropCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 518; + this.match(esql_parser.DROP); + this.state = 519; + this.qualifiedNames(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public renameVariable(): RenameVariableContext { + let _localctx: RenameVariableContext = new RenameVariableContext(this._ctx, this.state); + this.enterRule(_localctx, 86, esql_parser.RULE_renameVariable); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 521; + this.identifier(); + this.state = 526; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 52, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 522; + this.match(esql_parser.DOT); + this.state = 523; + this.identifier(); + } + } + } + this.state = 528; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 52, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public renameCommand(): RenameCommandContext { + let _localctx: RenameCommandContext = new RenameCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 88, esql_parser.RULE_renameCommand); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 529; + this.match(esql_parser.RENAME); + this.state = 530; + this.renameClause(); + this.state = 535; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 53, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 531; + this.match(esql_parser.COMMA); + this.state = 532; + this.renameClause(); + } + } + } + this.state = 537; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 53, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public renameClause(): RenameClauseContext { + let _localctx: RenameClauseContext = new RenameClauseContext(this._ctx, this.state); + this.enterRule(_localctx, 90, esql_parser.RULE_renameClause); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 538; + this.qualifiedName(); + this.state = 539; + this.match(esql_parser.AS); + this.state = 540; + this.renameVariable(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public dissectCommand(): DissectCommandContext { + let _localctx: DissectCommandContext = new DissectCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 92, esql_parser.RULE_dissectCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 542; + this.match(esql_parser.DISSECT); + this.state = 543; + this.qualifiedNames(); + this.state = 544; + this.string(); + this.state = 546; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 54, this._ctx) ) { + case 1: + { + this.state = 545; + this.commandOptions(); + } + break; + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public grokCommand(): GrokCommandContext { + let _localctx: GrokCommandContext = new GrokCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 94, esql_parser.RULE_grokCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 548; + this.match(esql_parser.GROK); + this.state = 549; + this.qualifiedNames(); + this.state = 550; + this.string(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public commandOptions(): CommandOptionsContext { + let _localctx: CommandOptionsContext = new CommandOptionsContext(this._ctx, this.state); + this.enterRule(_localctx, 96, esql_parser.RULE_commandOptions); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 552; + this.commandOption(); + this.state = 557; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 55, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 553; + this.match(esql_parser.COMMA); + this.state = 554; + this.commandOption(); + } + } + } + this.state = 559; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 55, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public commandOption(): CommandOptionContext { + let _localctx: CommandOptionContext = new CommandOptionContext(this._ctx, this.state); + this.enterRule(_localctx, 98, esql_parser.RULE_commandOption); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 560; + this.identifier(); + this.state = 561; + this.match(esql_parser.ASSIGN); + this.state = 562; + this.constant(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public booleanValue(): BooleanValueContext { + let _localctx: BooleanValueContext = new BooleanValueContext(this._ctx, this.state); + this.enterRule(_localctx, 100, esql_parser.RULE_booleanValue); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 564; + this.match(esql_parser.BOOLEAN_VALUE); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public number(): NumberContext { + let _localctx: NumberContext = new NumberContext(this._ctx, this.state); + this.enterRule(_localctx, 102, esql_parser.RULE_number); + try { + this.state = 568; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case esql_parser.DECIMAL_LITERAL: + _localctx = new DecimalLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 1); + { + this.state = 566; + this.match(esql_parser.DECIMAL_LITERAL); + } + break; + case esql_parser.INTEGER_LITERAL: + _localctx = new IntegerLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 2); + { + this.state = 567; + this.match(esql_parser.INTEGER_LITERAL); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public decimalValue(): DecimalValueContext { + let _localctx: DecimalValueContext = new DecimalValueContext(this._ctx, this.state); + this.enterRule(_localctx, 104, esql_parser.RULE_decimalValue); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 570; + this.match(esql_parser.DECIMAL_LITERAL); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public integerValue(): IntegerValueContext { + let _localctx: IntegerValueContext = new IntegerValueContext(this._ctx, this.state); + this.enterRule(_localctx, 106, esql_parser.RULE_integerValue); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 572; + this.match(esql_parser.INTEGER_LITERAL); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public string(): StringContext { + let _localctx: StringContext = new StringContext(this._ctx, this.state); + this.enterRule(_localctx, 108, esql_parser.RULE_string); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 574; + this.match(esql_parser.STRING); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public comparisonOperator(): ComparisonOperatorContext { + let _localctx: ComparisonOperatorContext = new ComparisonOperatorContext(this._ctx, this.state); + this.enterRule(_localctx, 110, esql_parser.RULE_comparisonOperator); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 576; + this.match(esql_parser.COMPARISON_OPERATOR); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public explainCommand(): ExplainCommandContext { + let _localctx: ExplainCommandContext = new ExplainCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 112, esql_parser.RULE_explainCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 578; + this.match(esql_parser.EXPLAIN); + this.state = 579; + this.subqueryExpression(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public subqueryExpression(): SubqueryExpressionContext { + let _localctx: SubqueryExpressionContext = new SubqueryExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 114, esql_parser.RULE_subqueryExpression); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 581; + this.match(esql_parser.OPENING_BRACKET); + this.state = 582; + this.query(0); + this.state = 583; + this.match(esql_parser.CLOSING_BRACKET); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public showCommand(): ShowCommandContext { + let _localctx: ShowCommandContext = new ShowCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 116, esql_parser.RULE_showCommand); + try { + this.state = 589; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 57, this._ctx) ) { + case 1: + this.enterOuterAlt(_localctx, 1); + { + this.state = 585; + this.match(esql_parser.SHOW); + this.state = 586; + this.match(esql_parser.INFO); + } + break; + + case 2: + this.enterOuterAlt(_localctx, 2); + { + this.state = 587; + this.match(esql_parser.SHOW); + this.state = 588; + this.match(esql_parser.FUNCTIONS); + } + break; + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + + public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { + switch (ruleIndex) { + case 1: + return this.query_sempred(_localctx as QueryContext, predIndex); + + case 8: + return this.whereBooleanExpression_sempred(_localctx as WhereBooleanExpressionContext, predIndex); + + case 9: + return this.booleanExpression_sempred(_localctx as BooleanExpressionContext, predIndex); + + case 15: + return this.operatorExpression_sempred(_localctx as OperatorExpressionContext, predIndex); + } + return true; + } + private query_sempred(_localctx: QueryContext, predIndex: number): boolean { + switch (predIndex) { + case 0: + return this.precpred(this._ctx, 1); + } + return true; + } + private whereBooleanExpression_sempred(_localctx: WhereBooleanExpressionContext, predIndex: number): boolean { + switch (predIndex) { + case 1: + return this.precpred(this._ctx, 5); + + case 2: + return this.precpred(this._ctx, 4); + } + return true; + } + private booleanExpression_sempred(_localctx: BooleanExpressionContext, predIndex: number): boolean { + switch (predIndex) { + case 3: + return this.precpred(this._ctx, 2); + + case 4: + return this.precpred(this._ctx, 1); + } + return true; + } + private operatorExpression_sempred(_localctx: OperatorExpressionContext, predIndex: number): boolean { + switch (predIndex) { + case 5: + return this.precpred(this._ctx, 2); + + case 6: + return this.precpred(this._ctx, 1); + } + return true; + } + + private static readonly _serializedATNSegments: number = 2; + private static readonly _serializedATNSegment0: string = + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x03S\u0252\x04\x02" + + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + + "\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t\x17\x04" + + "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + + "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + + "\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x04)\t)\x04*\t*\x04+\t+" + + "\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x040\t0\x041\t1\x042\t2\x043\t3\x044" + + "\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04:\t:\x04;\t;\x04<\t<\x03" + + "\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x07" + + "\x03\x82\n\x03\f\x03\x0E\x03\x85\v\x03\x03\x04\x03\x04\x03\x04\x03\x04" + + "\x05\x04\x8B\n\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x05\x05\x9A\n\x05" + + "\x03\x06\x03\x06\x03\x06\x03\x06\x05\x06\xA0\n\x06\x03\x06\x03\x06\x03" + + "\x06\x03\x06\x07\x06\xA6\n\x06\f\x06\x0E\x06\xA9\v\x06\x05\x06\xAB\n\x06" + + "\x03\x07\x03\x07\x03\x07\x05\x07\xB0\n\x07\x03\x07\x03\x07\x03\b\x03\b" + + "\x03\b\x03\t\x03\t\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x05" + + "\n\xC1\n\n\x03\n\x03\n\x03\n\x03\n\x03\n\x07\n\xC8\n\n\f\n\x0E\n\xCB\v" + + "\n\x03\n\x03\n\x03\n\x05\n\xD0\n\n\x03\n\x03\n\x03\n\x03\n\x03\n\x07\n" + + "\xD7\n\n\f\n\x0E\n\xDA\v\n\x05\n\xDC\n\n\x03\n\x03\n\x03\n\x03\n\x03\n" + + "\x05\n\xE3\n\n\x03\n\x03\n\x05\n\xE7\n\n\x03\n\x03\n\x03\n\x03\n\x03\n" + + "\x03\n\x07\n\xEF\n\n\f\n\x0E\n\xF2\v\n\x03\v\x03\v\x03\v\x03\v\x05\v\xF8" + + "\n\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x07\v\u0100\n\v\f\v\x0E\v\u0103" + + "\v\v\x03\f\x03\f\x05\f\u0107\n\f\x03\f\x03\f\x03\f\x03\f\x03\f\x05\f\u010E" + + "\n\f\x03\f\x03\f\x03\f\x05\f\u0113\n\f\x03\r\x03\r\x05\r\u0117\n\r\x03" + + "\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x07" + + "\x0F\u0122\n\x0F\f\x0F\x0E\x0F\u0125\v\x0F\x05\x0F\u0127\n\x0F\x03\x0F" + + "\x03\x0F\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x07\x10\u0130\n\x10\f" + + "\x10\x0E\x10\u0133\v\x10\x05\x10\u0135\n\x10\x03\x10\x03\x10\x03\x11\x03" + + "\x11\x03\x11\x03\x11\x03\x11\x03\x11\x05\x11\u013F\n\x11\x03\x11\x03\x11" + + "\x03\x11\x03\x11\x03\x11\x03\x11\x07\x11\u0147\n\x11\f\x11\x0E\x11\u014A" + + "\v\x11\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12" + + "\x03\x12\x03\x12\x03\x12\x07\x12\u0157\n\x12\f\x12\x0E\x12\u015A\v\x12" + + "\x05\x12\u015C\n\x12\x03\x12\x03\x12\x05\x12\u0160\n\x12\x03\x13\x03\x13" + + "\x03\x13\x03\x14\x03\x14\x03\x14\x07\x14\u0168\n\x14\f\x14\x0E\x14\u016B" + + "\v\x14\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15\x05\x15\u0172\n\x15\x03" + + "\x16\x03\x16\x03\x17\x03\x17\x03\x18\x03\x18\x03\x18\x03\x18\x07\x18\u017C" + + "\n\x18\f\x18\x0E\x18\u017F\v\x18\x03\x18\x05\x18\u0182\n\x18\x03\x19\x03" + + "\x19\x03\x19\x03\x19\x03\x19\x07\x19\u0189\n\x19\f\x19\x0E\x19\u018C\v" + + "\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x05\x1B\u0195" + + "\n\x1B\x03\x1B\x03\x1B\x05\x1B\u0199\n\x1B\x03\x1C\x03\x1C\x03\x1D\x03" + + "\x1D\x03\x1E\x03\x1E\x03\x1E\x05\x1E\u01A2\n\x1E\x03\x1F\x03\x1F\x03\x1F" + + "\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x05\x1F\u01AC\n\x1F\x03 \x03" + + " \x03 \x07 \u01B1\n \f \x0E \u01B4\v \x03!\x03!\x03!\x07!\u01B9\n!\f!" + + "\x0E!\u01BC\v!\x03\"\x03\"\x03#\x03#\x03$\x03$\x03%\x03%\x03%\x03%\x03" + + "%\x03%\x03%\x03%\x07%\u01CC\n%\f%\x0E%\u01CF\v%\x03%\x03%\x03%\x03%\x03" + + "%\x03%\x07%\u01D7\n%\f%\x0E%\u01DA\v%\x03%\x03%\x03%\x03%\x03%\x03%\x07" + + "%\u01E2\n%\f%\x0E%\u01E5\v%\x03%\x03%\x05%\u01E9\n%\x03&\x03&\x05&\u01ED" + + "\n&\x03\'\x03\'\x03\'\x03(\x03(\x03(\x03(\x07(\u01F6\n(\f(\x0E(\u01F9" + + "\v(\x03)\x03)\x05)\u01FD\n)\x03)\x03)\x05)\u0201\n)\x03*\x03*\x03*\x03" + + "+\x03+\x03+\x03,\x03,\x03,\x03-\x03-\x03-\x07-\u020F\n-\f-\x0E-\u0212" + + "\v-\x03.\x03.\x03.\x03.\x07.\u0218\n.\f.\x0E.\u021B\v.\x03/\x03/\x03/" + + "\x03/\x030\x030\x030\x030\x050\u0225\n0\x031\x031\x031\x031\x032\x032" + + "\x032\x072\u022E\n2\f2\x0E2\u0231\v2\x033\x033\x033\x033\x034\x034\x03" + + "5\x035\x055\u023B\n5\x036\x036\x037\x037\x038\x038\x039\x039\x03:\x03" + + ":\x03:\x03;\x03;\x03;\x03;\x03<\x03<\x03<\x03<\x05<\u0250\n<\x03<\x02" + + "\x02\x06\x04\x12\x14 =\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02" + + "\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02" + + "\"\x02$\x02&\x02(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02" + + ">\x02@\x02B\x02D\x02F\x02H\x02J\x02L\x02N\x02P\x02R\x02T\x02V\x02X\x02" + + "Z\x02\\\x02^\x02`\x02b\x02d\x02f\x02h\x02j\x02l\x02n\x02p\x02r\x02t\x02" + + "v\x02\x02\x07\x03\x0256\x03\x0279\x03\x02NO\x03\x02GH\x04\x0277AB\x02" + + "\u026F\x02x\x03\x02\x02\x02\x04{\x03\x02\x02\x02\x06\x8A\x03\x02\x02\x02" + + "\b\x99\x03\x02\x02\x02\n\x9B\x03\x02\x02\x02\f\xAF\x03\x02\x02\x02\x0E" + + "\xB3\x03\x02\x02\x02\x10\xB6\x03\x02\x02\x02\x12\xE6\x03\x02\x02\x02\x14" + + "\xF7\x03\x02\x02\x02\x16\u0112\x03\x02\x02\x02\x18\u0116\x03\x02\x02\x02" + + "\x1A\u0118\x03\x02\x02\x02\x1C\u011C\x03\x02\x02\x02\x1E\u012A\x03\x02" + + "\x02\x02 \u013E\x03\x02\x02\x02\"\u015F\x03\x02\x02\x02$\u0161\x03\x02" + + "\x02\x02&\u0164\x03\x02\x02\x02(\u0171\x03\x02\x02\x02*\u0173\x03\x02" + + "\x02\x02,\u0175\x03\x02\x02\x02.\u0177\x03\x02\x02\x020\u0183\x03\x02" + + "\x02\x022\u018F\x03\x02\x02\x024\u0192\x03\x02\x02\x026\u019A\x03\x02" + + "\x02\x028\u019C\x03\x02\x02\x02:\u01A1\x03\x02\x02\x02<\u01AB\x03\x02" + + "\x02\x02>\u01AD\x03\x02\x02\x02@\u01B5\x03\x02\x02\x02B\u01BD\x03\x02" + + "\x02\x02D\u01BF\x03\x02\x02\x02F\u01C1\x03\x02\x02\x02H\u01E8\x03\x02" + + "\x02\x02J\u01EC\x03\x02\x02\x02L\u01EE\x03\x02\x02\x02N\u01F1\x03\x02" + + "\x02\x02P\u01FA\x03\x02\x02\x02R\u0202\x03\x02\x02\x02T\u0205\x03\x02" + + "\x02\x02V\u0208\x03\x02\x02\x02X\u020B\x03\x02\x02\x02Z\u0213\x03\x02" + + "\x02\x02\\\u021C\x03\x02\x02\x02^\u0220\x03\x02\x02\x02`\u0226\x03\x02" + + "\x02\x02b\u022A\x03\x02\x02\x02d\u0232\x03\x02\x02\x02f\u0236\x03\x02" + + "\x02\x02h\u023A\x03\x02\x02\x02j\u023C\x03\x02\x02\x02l\u023E\x03\x02" + + "\x02\x02n\u0240\x03\x02\x02\x02p\u0242\x03\x02\x02\x02r\u0244\x03\x02" + + "\x02\x02t\u0247\x03\x02\x02\x02v\u024F\x03\x02\x02\x02xy\x05\x04\x03\x02" + + "yz\x07\x02\x02\x03z\x03\x03\x02\x02\x02{|\b\x03\x01\x02|}\x05\x06\x04" + + "\x02}\x83\x03\x02\x02\x02~\x7F\f\x03\x02\x02\x7F\x80\x07\x1A\x02\x02\x80" + + "\x82\x05\b\x05\x02\x81~\x03\x02\x02\x02\x82\x85\x03\x02\x02\x02\x83\x81" + + "\x03\x02\x02\x02\x83\x84\x03\x02\x02\x02\x84\x05\x03\x02\x02\x02\x85\x83" + + "\x03\x02\x02\x02\x86\x8B\x05r:\x02\x87\x8B\x05.\x18\x02\x88\x8B\x05$\x13" + + "\x02\x89\x8B\x05v<\x02\x8A\x86\x03\x02\x02\x02\x8A\x87\x03\x02\x02\x02" + + "\x8A\x88\x03\x02\x02\x02\x8A\x89\x03\x02\x02\x02\x8B\x07\x03\x02\x02\x02" + + "\x8C\x9A\x052\x1A\x02\x8D\x9A\x05L\'\x02\x8E\x9A\x05R*\x02\x8F\x9A\x05" + + "T+\x02\x90\x9A\x05Z.\x02\x91\x9A\x05V,\x02\x92\x9A\x05^0\x02\x93\x9A\x05" + + "`1\x02\x94\x9A\x05N(\x02\x95\x9A\x054\x1B\x02\x96\x9A\x05\x10\t\x02\x97" + + "\x9A\x05\x0E\b\x02\x98\x9A\x05\n\x06\x02\x99\x8C\x03\x02\x02\x02\x99\x8D" + + "\x03\x02\x02\x02\x99\x8E\x03\x02\x02\x02\x99\x8F\x03\x02\x02\x02\x99\x90" + + "\x03\x02\x02\x02\x99\x91\x03\x02\x02\x02\x99\x92\x03\x02\x02\x02\x99\x93" + + "\x03\x02\x02\x02\x99\x94\x03\x02\x02\x02\x99\x95\x03\x02\x02\x02\x99\x96" + + "\x03\x02\x02\x02\x99\x97\x03\x02\x02\x02\x99\x98\x03\x02\x02\x02\x9A\t" + + "\x03\x02\x02\x02\x9B\x9C\x07\x12\x02\x02\x9C\x9F\x058\x1D\x02\x9D\x9E" + + "\x07L\x02\x02\x9E\xA0\x05*\x16\x02\x9F\x9D\x03\x02\x02\x02\x9F\xA0\x03" + + "\x02\x02\x02\xA0\xAA\x03\x02\x02\x02\xA1\xA2\x07M\x02\x02\xA2\xA7\x05" + + "\f\x07\x02\xA3\xA4\x07\"\x02\x02\xA4\xA6\x05\f\x07\x02\xA5\xA3\x03\x02" + + "\x02\x02\xA6\xA9\x03\x02\x02\x02\xA7\xA5\x03\x02\x02\x02\xA7\xA8\x03\x02" + + "\x02\x02\xA8\xAB\x03\x02\x02\x02\xA9\xA7\x03\x02\x02\x02\xAA\xA1\x03\x02" + + "\x02\x02\xAA\xAB\x03\x02\x02\x02\xAB\v\x03\x02\x02\x02\xAC\xAD\x05*\x16" + + "\x02\xAD\xAE\x07!\x02\x02\xAE\xB0\x03\x02\x02\x02\xAF\xAC\x03\x02\x02" + + "\x02\xAF\xB0\x03\x02\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2\x05*\x16" + + "\x02\xB2\r\x03\x02\x02\x02\xB3\xB4\x07\f\x02\x02\xB4\xB5\x05@!\x02\xB5" + + "\x0F\x03\x02\x02\x02\xB6\xB7\x07\n\x02\x02\xB7\xB8\x05\x12\n\x02\xB8\x11" + + "\x03\x02\x02\x02\xB9\xBA\b\n\x01\x02\xBA\xBB\x07\'\x02\x02\xBB\xE7\x05" + + "\x12\n\n\xBC\xE7\x05\x18\r\x02\xBD\xE7\x05\x16\f\x02\xBE\xC0\x05\x18\r" + + "\x02\xBF\xC1\x07\'\x02\x02\xC0\xBF\x03\x02\x02\x02\xC0\xC1\x03\x02\x02" + + "\x02\xC1\xC2\x03\x02\x02\x02\xC2\xC3\x07*\x02\x02\xC3\xC4\x07$\x02\x02" + + "\xC4\xC9\x05\x18\r\x02\xC5\xC6\x07\"\x02\x02\xC6\xC8\x05\x18\r\x02\xC7" + + "\xC5\x03\x02\x02\x02\xC8\xCB\x03\x02\x02\x02\xC9\xC7\x03\x02\x02\x02\xC9" + + "\xCA\x03\x02\x02\x02\xCA\xCC\x03\x02\x02\x02\xCB\xC9\x03\x02\x02\x02\xCC" + + "\xCD\x07/\x02\x02\xCD\xE7\x03\x02\x02\x02\xCE\xD0\x07\'\x02\x02\xCF\xCE" + + "\x03\x02\x02\x02\xCF\xD0\x03\x02\x02\x02\xD0\xD1\x03\x02\x02\x02\xD1\xD2" + + "\x07@\x02\x02\xD2\xD3\x07$\x02\x02\xD3\xDB\x05> \x02\xD4\xD5\x07\"\x02" + + "\x02\xD5\xD7\x05:\x1E\x02\xD6\xD4\x03\x02\x02\x02\xD7\xDA\x03\x02\x02" + + "\x02\xD8\xD6\x03\x02\x02\x02\xD8\xD9\x03\x02\x02\x02\xD9\xDC\x03\x02\x02" + + "\x02\xDA\xD8\x03\x02\x02\x02\xDB\xD8\x03\x02\x02\x02\xDB\xDC\x03\x02\x02" + + "\x02\xDC\xDD\x03\x02\x02\x02\xDD\xDE\x07/\x02\x02\xDE\xE7\x03\x02\x02" + + "\x02\xDF\xE0\x05\x18\r\x02\xE0\xE2\x07+\x02\x02\xE1\xE3\x07\'\x02\x02" + + "\xE2\xE1\x03\x02\x02\x02\xE2\xE3\x03\x02\x02\x02\xE3\xE4\x03\x02\x02\x02" + + "\xE4\xE5\x07-\x02\x02\xE5\xE7\x03\x02\x02\x02\xE6\xB9\x03\x02\x02\x02" + + "\xE6\xBC\x03\x02\x02\x02\xE6\xBD\x03\x02\x02\x02\xE6\xBE\x03\x02\x02\x02" + + "\xE6\xCF\x03\x02\x02\x02\xE6\xDF\x03\x02\x02\x02\xE7\xF0\x03\x02\x02\x02" + + "\xE8\xE9\f\x07\x02\x02\xE9\xEA\x07 \x02\x02\xEA\xEF\x05\x12\n\b\xEB\xEC" + + "\f\x06\x02\x02\xEC\xED\x07.\x02\x02\xED\xEF\x05\x12\n\x07\xEE\xE8\x03" + + "\x02\x02\x02\xEE\xEB\x03\x02\x02\x02\xEF\xF2\x03\x02\x02\x02\xF0\xEE\x03" + + "\x02\x02\x02\xF0\xF1\x03\x02\x02\x02\xF1\x13\x03\x02\x02\x02\xF2\xF0\x03" + + "\x02\x02\x02\xF3\xF4\b\v\x01\x02\xF4\xF5\x07\'\x02\x02\xF5\xF8\x05\x14" + + "\v\x06\xF6\xF8\x05\x18\r\x02\xF7\xF3\x03\x02\x02\x02\xF7\xF6\x03\x02\x02" + + "\x02\xF8\u0101\x03\x02\x02\x02\xF9\xFA\f\x04\x02\x02\xFA\xFB\x07 \x02" + + "\x02\xFB\u0100\x05\x14\v\x05\xFC\xFD\f\x03\x02\x02\xFD\xFE\x07.\x02\x02" + + "\xFE\u0100\x05\x14\v\x04\xFF\xF9\x03\x02\x02\x02\xFF\xFC\x03\x02\x02\x02" + + "\u0100\u0103\x03\x02\x02\x02\u0101\xFF\x03\x02\x02\x02\u0101\u0102\x03" + + "\x02\x02\x02\u0102\x15\x03\x02\x02\x02\u0103\u0101\x03\x02\x02\x02\u0104" + + "\u0106\x05\x18\r\x02\u0105\u0107\x07\'\x02\x02\u0106\u0105\x03\x02\x02" + + "\x02\u0106\u0107\x03\x02\x02\x02\u0107\u0108\x03\x02\x02\x02\u0108\u0109" + + "\x07(\x02\x02\u0109\u010A\x05n8\x02\u010A\u0113\x03\x02\x02\x02\u010B" + + "\u010D\x05\x18\r\x02\u010C\u010E\x07\'\x02\x02\u010D\u010C\x03\x02\x02" + + "\x02\u010D\u010E\x03\x02\x02\x02\u010E\u010F\x03\x02\x02\x02\u010F\u0110" + + "\x07)\x02\x02\u0110\u0111\x05n8\x02\u0111\u0113\x03\x02\x02\x02\u0112" + + "\u0104\x03\x02\x02\x02\u0112\u010B\x03\x02\x02\x02\u0113\x17\x03\x02\x02" + + "\x02\u0114\u0117\x05 \x11\x02\u0115\u0117\x05\x1A\x0E\x02\u0116\u0114" + + "\x03\x02\x02\x02\u0116\u0115\x03\x02\x02\x02\u0117\x19\x03\x02\x02\x02" + + "\u0118\u0119\x05 \x11\x02\u0119\u011A\x05p9\x02\u011A\u011B\x05 \x11\x02" + + "\u011B\x1B\x03\x02\x02\x02\u011C\u011D\x05F$\x02\u011D\u0126\x07$\x02" + + "\x02\u011E\u0123\x05:\x1E\x02\u011F\u0120\x07\"\x02\x02\u0120\u0122\x05" + + ":\x1E\x02\u0121\u011F\x03\x02\x02\x02\u0122\u0125\x03\x02\x02\x02\u0123" + + "\u0121\x03\x02\x02\x02\u0123\u0124\x03\x02\x02\x02\u0124\u0127\x03\x02" + + "\x02\x02\u0125\u0123\x03\x02\x02\x02\u0126\u011E\x03\x02\x02\x02\u0126" + + "\u0127\x03\x02\x02\x02\u0127\u0128\x03\x02\x02\x02\u0128\u0129\x07/\x02" + + "\x02\u0129\x1D\x03\x02\x02\x02\u012A\u012B\x05D#\x02\u012B\u0134\x07$" + + "\x02\x02\u012C\u0131\x05<\x1F\x02\u012D\u012E\x07\"\x02\x02\u012E\u0130" + + "\x05<\x1F\x02\u012F\u012D\x03\x02\x02\x02\u0130\u0133\x03\x02\x02\x02" + + "\u0131\u012F\x03\x02\x02\x02\u0131\u0132\x03\x02\x02\x02\u0132\u0135\x03" + + "\x02\x02\x02\u0133\u0131\x03\x02\x02\x02\u0134\u012C\x03\x02\x02\x02\u0134" + + "\u0135\x03\x02\x02\x02\u0135\u0136\x03\x02\x02\x02\u0136\u0137\x07/\x02" + + "\x02\u0137\x1F\x03\x02\x02\x02\u0138\u0139\b\x11\x01\x02\u0139\u013F\x05" + + "\"\x12\x02\u013A\u013F\x05\x1C\x0F\x02\u013B\u013F\x05\x1E\x10\x02\u013C" + + "\u013D\t\x02\x02\x02\u013D\u013F\x05 \x11\x05\u013E\u0138\x03\x02\x02" + + "\x02\u013E\u013A\x03\x02\x02\x02\u013E\u013B\x03\x02\x02\x02\u013E\u013C" + + "\x03\x02\x02\x02\u013F\u0148\x03\x02\x02\x02\u0140\u0141\f\x04\x02\x02" + + "\u0141\u0142\t\x03\x02\x02\u0142\u0147\x05 \x11\x05\u0143\u0144\f\x03" + + "\x02\x02\u0144\u0145\t\x02\x02\x02\u0145\u0147\x05 \x11\x04\u0146\u0140" + + "\x03\x02\x02\x02\u0146\u0143\x03\x02\x02\x02\u0147\u014A\x03\x02\x02\x02" + + "\u0148\u0146\x03\x02\x02\x02\u0148\u0149\x03\x02\x02\x02\u0149!\x03\x02" + + "\x02\x02\u014A\u0148\x03\x02\x02\x02\u014B\u0160\x05H%\x02\u014C\u0160" + + "\x05> \x02\u014D\u014E\x07$\x02\x02\u014E\u014F\x05\x14\v\x02\u014F\u0150" + + "\x07/\x02\x02\u0150\u0160\x03\x02\x02\x02\u0151\u0152\x05B\"\x02\u0152" + + "\u015B\x07$\x02\x02\u0153\u0158\x05\x14\v\x02\u0154\u0155\x07\"\x02\x02" + + "\u0155\u0157\x05\x14\v\x02\u0156\u0154\x03\x02\x02\x02\u0157\u015A\x03" + + "\x02\x02\x02\u0158\u0156\x03\x02\x02\x02\u0158\u0159\x03\x02\x02\x02\u0159" + + "\u015C\x03\x02\x02\x02\u015A\u0158\x03\x02\x02\x02\u015B\u0153\x03\x02" + + "\x02\x02\u015B\u015C\x03\x02\x02\x02\u015C\u015D\x03\x02\x02\x02\u015D" + + "\u015E\x07/\x02\x02\u015E\u0160\x03\x02\x02\x02\u015F\u014B\x03\x02\x02" + + "\x02\u015F\u014C\x03\x02\x02\x02\u015F\u014D\x03\x02\x02\x02\u015F\u0151" + + "\x03\x02\x02\x02\u0160#\x03\x02\x02\x02\u0161\u0162\x07\b\x02\x02\u0162" + + "\u0163\x05&\x14\x02\u0163%\x03\x02\x02\x02\u0164\u0169\x05(\x15\x02\u0165" + + "\u0166\x07\"\x02\x02\u0166\u0168\x05(\x15\x02\u0167\u0165\x03\x02\x02" + + "\x02\u0168\u016B\x03\x02\x02\x02\u0169\u0167\x03\x02\x02\x02\u0169\u016A" + + "\x03\x02\x02\x02\u016A\'\x03\x02\x02\x02\u016B\u0169\x03\x02\x02\x02\u016C" + + "\u0172\x05\x14\v\x02\u016D\u016E\x05,\x17\x02\u016E\u016F\x07!\x02\x02" + + "\u016F\u0170\x05\x14\v\x02\u0170\u0172\x03\x02\x02\x02\u0171\u016C\x03" + + "\x02\x02\x02\u0171\u016D\x03\x02\x02\x02\u0172)\x03\x02\x02\x02\u0173" + + "\u0174\t\x04\x02\x02\u0174+\x03\x02\x02\x02\u0175\u0176\x05B\"\x02\u0176" + + "-\x03\x02\x02\x02\u0177\u0178\x07\x07\x02\x02\u0178\u017D\x056\x1C\x02" + + "\u0179\u017A\x07\"\x02\x02\u017A\u017C\x056\x1C\x02\u017B\u0179\x03\x02" + + "\x02\x02\u017C\u017F\x03\x02\x02\x02\u017D\u017B\x03\x02\x02\x02\u017D" + + "\u017E\x03\x02\x02\x02\u017E\u0181\x03\x02\x02\x02\u017F\u017D\x03\x02" + + "\x02\x02\u0180\u0182\x050\x19\x02\u0181\u0180\x03\x02\x02\x02\u0181\u0182" + + "\x03\x02\x02\x02\u0182/\x03\x02\x02\x02\u0183\u0184\x07%\x02\x02\u0184" + + "\u0185\x07F\x02\x02\u0185\u018A\x056\x1C\x02\u0186\u0187\x07\"\x02\x02" + + "\u0187\u0189\x056\x1C\x02\u0188\u0186\x03\x02\x02\x02\u0189\u018C\x03" + + "\x02\x02\x02\u018A\u0188\x03\x02\x02\x02\u018A\u018B\x03\x02\x02\x02\u018B" + + "\u018D\x03\x02\x02\x02\u018C\u018A\x03\x02\x02\x02\u018D\u018E\x07&\x02" + + "\x02\u018E1\x03\x02\x02\x02\u018F\u0190\x07\x05\x02\x02\u0190\u0191\x05" + + "&\x14\x02\u01913\x03\x02\x02\x02\u0192\u0194\x07\t\x02\x02\u0193\u0195" + + "\x05&\x14\x02\u0194\u0193\x03\x02\x02\x02\u0194\u0195\x03\x02\x02\x02" + + "\u0195\u0198\x03\x02\x02\x02\u0196\u0197\x07\x1E\x02\x02\u0197\u0199\x05" + + "@!\x02\u0198\u0196\x03\x02\x02\x02\u0198\u0199\x03\x02\x02\x02\u01995" + + "\x03\x02\x02\x02\u019A\u019B\t\x05\x02\x02\u019B7\x03\x02\x02\x02\u019C" + + "\u019D\t\x04\x02\x02\u019D9\x03\x02\x02\x02\u019E\u01A2\x05> \x02\u019F" + + "\u01A2\x05n8\x02\u01A0\u01A2\x05h5\x02\u01A1\u019E\x03\x02\x02\x02\u01A1" + + "\u019F\x03\x02\x02\x02\u01A1\u01A0\x03\x02\x02\x02\u01A2;\x03\x02\x02" + + "\x02\u01A3\u01AC\x05> \x02\u01A4\u01AC\x05n8\x02\u01A5\u01AC\x05h5\x02" + + "\u01A6\u01AC\x05 \x11\x02\u01A7\u01A8\x05h5\x02\u01A8\u01A9\x07\x1F\x02" + + "\x02\u01A9\u01AC\x03\x02\x02\x02\u01AA\u01AC\x05\x1A\x0E\x02\u01AB\u01A3" + + "\x03\x02\x02\x02\u01AB\u01A4\x03\x02\x02\x02\u01AB\u01A5\x03\x02\x02\x02" + + "\u01AB\u01A6\x03\x02\x02\x02\u01AB\u01A7\x03\x02\x02\x02\u01AB\u01AA\x03" + + "\x02\x02\x02\u01AC=\x03\x02\x02\x02\u01AD\u01B2\x05B\"\x02\u01AE\u01AF" + + "\x07#\x02\x02\u01AF\u01B1\x05B\"\x02\u01B0\u01AE\x03\x02\x02\x02\u01B1" + + "\u01B4\x03\x02\x02\x02\u01B2\u01B0\x03\x02\x02\x02\u01B2\u01B3\x03\x02" + + "\x02\x02\u01B3?\x03\x02\x02\x02\u01B4\u01B2\x03\x02\x02\x02\u01B5\u01BA" + + "\x05> \x02\u01B6\u01B7\x07\"\x02\x02\u01B7\u01B9\x05> \x02\u01B8\u01B6" + + "\x03\x02\x02\x02\u01B9\u01BC\x03\x02\x02\x02\u01BA\u01B8\x03\x02\x02\x02" + + "\u01BA\u01BB\x03\x02\x02\x02\u01BBA\x03\x02\x02\x02\u01BC\u01BA\x03\x02" + + "\x02\x02\u01BD\u01BE\t\x06\x02\x02\u01BEC\x03\x02\x02\x02\u01BF\u01C0" + + "\x07>\x02\x02\u01C0E\x03\x02\x02\x02\u01C1\u01C2\x07?\x02\x02\u01C2G\x03" + + "\x02\x02\x02\u01C3\u01E9\x07-\x02\x02\u01C4\u01E9\x05J&\x02\u01C5\u01E9" + + "\x05f4\x02\u01C6\u01E9\x05n8\x02\u01C7\u01C8\x07%\x02\x02\u01C8\u01CD" + + "\x05J&\x02\u01C9\u01CA\x07\"\x02\x02\u01CA\u01CC\x05J&\x02\u01CB\u01C9" + + "\x03\x02\x02\x02\u01CC\u01CF\x03\x02\x02\x02\u01CD\u01CB\x03\x02\x02\x02" + + "\u01CD\u01CE\x03\x02\x02\x02\u01CE\u01D0\x03\x02\x02\x02\u01CF\u01CD\x03" + + "\x02\x02\x02\u01D0\u01D1\x07&\x02\x02\u01D1\u01E9\x03\x02\x02\x02\u01D2" + + "\u01D3\x07%\x02\x02\u01D3\u01D8\x05f4\x02\u01D4\u01D5\x07\"\x02\x02\u01D5" + + "\u01D7\x05f4\x02\u01D6\u01D4\x03\x02\x02\x02\u01D7\u01DA\x03\x02\x02\x02" + + "\u01D8\u01D6\x03\x02\x02\x02\u01D8\u01D9\x03\x02\x02\x02\u01D9\u01DB\x03" + + "\x02\x02\x02\u01DA\u01D8\x03\x02\x02\x02\u01DB\u01DC\x07&\x02\x02\u01DC" + + "\u01E9\x03\x02\x02\x02\u01DD\u01DE\x07%\x02\x02\u01DE\u01E3\x05n8\x02" + + "\u01DF\u01E0\x07\"\x02\x02\u01E0\u01E2\x05n8\x02\u01E1\u01DF\x03\x02\x02" + + "\x02\u01E2\u01E5\x03\x02\x02\x02\u01E3\u01E1\x03\x02\x02\x02\u01E3\u01E4" + + "\x03\x02\x02\x02\u01E4\u01E6\x03\x02\x02\x02\u01E5\u01E3\x03\x02\x02\x02" + + "\u01E6\u01E7\x07&\x02\x02\u01E7\u01E9\x03\x02\x02\x02\u01E8\u01C3\x03" + + "\x02\x02\x02\u01E8\u01C4\x03\x02\x02\x02\u01E8\u01C5\x03\x02\x02\x02\u01E8" + + "\u01C6\x03\x02\x02\x02\u01E8\u01C7\x03\x02\x02\x02\u01E8\u01D2\x03\x02" + + "\x02\x02\u01E8\u01DD\x03\x02\x02\x02\u01E9I\x03\x02\x02\x02\u01EA\u01ED" + + "\x05j6\x02\u01EB\u01ED\x05l7\x02\u01EC\u01EA\x03\x02\x02\x02\u01EC\u01EB" + + "\x03\x02\x02\x02\u01EDK\x03\x02\x02\x02\u01EE\u01EF\x07\r\x02\x02\u01EF" + + "\u01F0\x07\x1C\x02\x02\u01F0M\x03\x02\x02\x02\u01F1\u01F2\x07\v\x02\x02" + + "\u01F2\u01F7\x05P)\x02\u01F3\u01F4\x07\"\x02\x02\u01F4\u01F6\x05P)\x02" + + "\u01F5\u01F3\x03\x02\x02\x02\u01F6\u01F9\x03\x02\x02\x02\u01F7\u01F5\x03" + + "\x02\x02\x02\u01F7\u01F8\x03\x02\x02\x02\u01F8O\x03\x02\x02\x02\u01F9" + + "\u01F7\x03\x02\x02\x02\u01FA\u01FC\x05\x14\v\x02\u01FB\u01FD\x07;\x02" + + "\x02\u01FC\u01FB\x03\x02\x02\x02\u01FC\u01FD\x03\x02\x02\x02\u01FD\u0200" + + "\x03\x02\x02\x02\u01FE\u01FF\x07<\x02\x02\u01FF\u0201\x07=\x02\x02\u0200" + + "\u01FE\x03\x02\x02\x02\u0200\u0201\x03\x02\x02\x02\u0201Q\x03\x02\x02" + + "\x02\u0202\u0203\x07\x0E\x02\x02\u0203\u0204\x05@!\x02\u0204S\x03\x02" + + "\x02\x02\u0205\u0206\x07\x13\x02\x02\u0206\u0207\x05@!\x02\u0207U\x03" + + "\x02\x02\x02\u0208\u0209\x07\x0F\x02\x02\u0209\u020A\x05@!\x02\u020AW" + + "\x03\x02\x02\x02\u020B\u0210\x05B\"\x02\u020C\u020D\x07#\x02\x02\u020D" + + "\u020F\x05B\"\x02\u020E\u020C\x03\x02\x02\x02\u020F\u0212\x03\x02\x02" + + "\x02\u0210\u020E\x03\x02\x02\x02\u0210\u0211\x03\x02\x02\x02\u0211Y\x03" + + "\x02\x02\x02\u0212\u0210\x03\x02\x02\x02\u0213\u0214\x07\x10\x02\x02\u0214" + + "\u0219\x05\\/\x02\u0215\u0216\x07\"\x02\x02\u0216\u0218\x05\\/\x02\u0217" + + "\u0215\x03\x02\x02\x02\u0218\u021B\x03\x02\x02\x02\u0219\u0217\x03\x02" + + "\x02\x02\u0219\u021A\x03\x02\x02\x02\u021A[\x03\x02\x02\x02\u021B\u0219" + + "\x03\x02\x02\x02\u021C\u021D\x05> \x02\u021D\u021E\x07,\x02\x02\u021E" + + "\u021F\x05X-\x02\u021F]\x03\x02\x02\x02\u0220\u0221\x07\x03\x02\x02\u0221" + + "\u0222\x05@!\x02\u0222\u0224\x05n8\x02\u0223\u0225\x05b2\x02\u0224\u0223" + + "\x03\x02\x02\x02\u0224\u0225\x03\x02\x02\x02\u0225_\x03\x02\x02\x02\u0226" + + "\u0227\x07\x04\x02\x02\u0227\u0228\x05@!\x02\u0228\u0229\x05n8\x02\u0229" + + "a\x03\x02\x02\x02\u022A\u022F\x05d3\x02\u022B\u022C\x07\"\x02\x02\u022C" + + "\u022E\x05d3\x02\u022D\u022B\x03\x02\x02\x02\u022E\u0231\x03\x02\x02\x02" + + "\u022F\u022D\x03\x02\x02\x02\u022F\u0230\x03\x02\x02\x02\u0230c\x03\x02" + + "\x02\x02\u0231\u022F\x03\x02\x02\x02\u0232\u0233\x05B\"\x02\u0233\u0234" + + "\x07!\x02\x02\u0234\u0235\x05H%\x02\u0235e\x03\x02\x02\x02\u0236\u0237" + + "\x073\x02\x02\u0237g\x03\x02\x02\x02\u0238\u023B\x07\x1D\x02\x02\u0239" + + "\u023B\x07\x1C\x02"; + private static readonly _serializedATNSegment1: string = + "\x02\u023A\u0238\x03\x02\x02\x02\u023A\u0239\x03\x02\x02\x02\u023Bi\x03" + + "\x02\x02\x02\u023C\u023D\x07\x1D\x02\x02\u023Dk\x03\x02\x02\x02\u023E" + + "\u023F\x07\x1C\x02\x02\u023Fm\x03\x02\x02\x02\u0240\u0241\x07\x1B\x02" + + "\x02\u0241o\x03\x02\x02\x02\u0242\u0243\x074\x02\x02\u0243q\x03\x02\x02" + + "\x02\u0244\u0245\x07\x06\x02\x02\u0245\u0246\x05t;\x02\u0246s\x03\x02" + + "\x02\x02\u0247\u0248\x07%\x02\x02\u0248\u0249\x05\x04\x03\x02\u0249\u024A" + + "\x07&\x02\x02\u024Au\x03\x02\x02\x02\u024B\u024C\x07\x11\x02\x02\u024C" + + "\u0250\x071\x02\x02\u024D\u024E\x07\x11\x02\x02\u024E\u0250\x072\x02\x02" + + "\u024F\u024B\x03\x02\x02\x02\u024F\u024D\x03\x02\x02\x02\u0250w\x03\x02" + + "\x02\x02<\x83\x8A\x99\x9F\xA7\xAA\xAF\xC0\xC9\xCF\xD8\xDB\xE2\xE6\xEE" + + "\xF0\xF7\xFF\u0101\u0106\u010D\u0112\u0116\u0123\u0126\u0131\u0134\u013E" + + "\u0146\u0148\u0158\u015B\u015F\u0169\u0171\u017D\u0181\u018A\u0194\u0198" + + "\u01A1\u01AB\u01B2\u01BA\u01CD\u01D8\u01E3\u01E8\u01EC\u01F7\u01FC\u0200" + + "\u0210\u0219\u0224\u022F\u023A\u024F"; + public static readonly _serializedATN: string = Utils.join( + [ + esql_parser._serializedATNSegment0, + esql_parser._serializedATNSegment1, + ], + "", + ); + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!esql_parser.__ATN) { + esql_parser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(esql_parser._serializedATN)); + } + + return esql_parser.__ATN; + } + +} + +export class SingleStatementContext extends ParserRuleContext { + public query(): QueryContext { + return this.getRuleContext(0, QueryContext); + } + public EOF(): TerminalNode { return this.getToken(esql_parser.EOF, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_singleStatement; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterSingleStatement) { + listener.enterSingleStatement(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitSingleStatement) { + listener.exitSingleStatement(this); + } + } +} + + +export class QueryContext extends ParserRuleContext { + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_query; } + public copyFrom(ctx: QueryContext): void { + super.copyFrom(ctx); + } +} +export class SingleCommandQueryContext extends QueryContext { + public sourceCommand(): SourceCommandContext { + return this.getRuleContext(0, SourceCommandContext); + } + constructor(ctx: QueryContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterSingleCommandQuery) { + listener.enterSingleCommandQuery(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitSingleCommandQuery) { + listener.exitSingleCommandQuery(this); + } + } +} +export class CompositeQueryContext extends QueryContext { + public query(): QueryContext { + return this.getRuleContext(0, QueryContext); + } + public PIPE(): TerminalNode { return this.getToken(esql_parser.PIPE, 0); } + public processingCommand(): ProcessingCommandContext { + return this.getRuleContext(0, ProcessingCommandContext); + } + constructor(ctx: QueryContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterCompositeQuery) { + listener.enterCompositeQuery(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitCompositeQuery) { + listener.exitCompositeQuery(this); + } + } +} + + +export class SourceCommandContext extends ParserRuleContext { + public explainCommand(): ExplainCommandContext | undefined { + return this.tryGetRuleContext(0, ExplainCommandContext); + } + public fromCommand(): FromCommandContext | undefined { + return this.tryGetRuleContext(0, FromCommandContext); + } + public rowCommand(): RowCommandContext | undefined { + return this.tryGetRuleContext(0, RowCommandContext); + } + public showCommand(): ShowCommandContext | undefined { + return this.tryGetRuleContext(0, ShowCommandContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_sourceCommand; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterSourceCommand) { + listener.enterSourceCommand(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitSourceCommand) { + listener.exitSourceCommand(this); + } + } +} + + +export class ProcessingCommandContext extends ParserRuleContext { + public evalCommand(): EvalCommandContext | undefined { + return this.tryGetRuleContext(0, EvalCommandContext); + } + public limitCommand(): LimitCommandContext | undefined { + return this.tryGetRuleContext(0, LimitCommandContext); + } + public projectCommand(): ProjectCommandContext | undefined { + return this.tryGetRuleContext(0, ProjectCommandContext); + } + public keepCommand(): KeepCommandContext | undefined { + return this.tryGetRuleContext(0, KeepCommandContext); + } + public renameCommand(): RenameCommandContext | undefined { + return this.tryGetRuleContext(0, RenameCommandContext); + } + public dropCommand(): DropCommandContext | undefined { + return this.tryGetRuleContext(0, DropCommandContext); + } + public dissectCommand(): DissectCommandContext | undefined { + return this.tryGetRuleContext(0, DissectCommandContext); + } + public grokCommand(): GrokCommandContext | undefined { + return this.tryGetRuleContext(0, GrokCommandContext); + } + public sortCommand(): SortCommandContext | undefined { + return this.tryGetRuleContext(0, SortCommandContext); + } + public statsCommand(): StatsCommandContext | undefined { + return this.tryGetRuleContext(0, StatsCommandContext); + } + public whereCommand(): WhereCommandContext | undefined { + return this.tryGetRuleContext(0, WhereCommandContext); + } + public mvExpandCommand(): MvExpandCommandContext | undefined { + return this.tryGetRuleContext(0, MvExpandCommandContext); + } + public enrichCommand(): EnrichCommandContext | undefined { + return this.tryGetRuleContext(0, EnrichCommandContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_processingCommand; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterProcessingCommand) { + listener.enterProcessingCommand(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitProcessingCommand) { + listener.exitProcessingCommand(this); + } + } +} + + +export class EnrichCommandContext extends ParserRuleContext { + public _policyName: EnrichIdentifierContext; + public _matchField: EnrichFieldIdentifierContext; + public ENRICH(): TerminalNode { return this.getToken(esql_parser.ENRICH, 0); } + public enrichIdentifier(): EnrichIdentifierContext { + return this.getRuleContext(0, EnrichIdentifierContext); + } + public ON(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ON, 0); } + public WITH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.WITH, 0); } + public enrichWithClause(): EnrichWithClauseContext[]; + public enrichWithClause(i: number): EnrichWithClauseContext; + public enrichWithClause(i?: number): EnrichWithClauseContext | EnrichWithClauseContext[] { + if (i === undefined) { + return this.getRuleContexts(EnrichWithClauseContext); + } else { + return this.getRuleContext(i, EnrichWithClauseContext); + } + } + public enrichFieldIdentifier(): EnrichFieldIdentifierContext | undefined { + return this.tryGetRuleContext(0, EnrichFieldIdentifierContext); + } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_enrichCommand; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterEnrichCommand) { + listener.enterEnrichCommand(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitEnrichCommand) { + listener.exitEnrichCommand(this); + } + } +} + + +export class EnrichWithClauseContext extends ParserRuleContext { + public _newName: EnrichFieldIdentifierContext; + public _enrichField: EnrichFieldIdentifierContext; + public enrichFieldIdentifier(): EnrichFieldIdentifierContext[]; + public enrichFieldIdentifier(i: number): EnrichFieldIdentifierContext; + public enrichFieldIdentifier(i?: number): EnrichFieldIdentifierContext | EnrichFieldIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(EnrichFieldIdentifierContext); + } else { + return this.getRuleContext(i, EnrichFieldIdentifierContext); + } + } + public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_enrichWithClause; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterEnrichWithClause) { + listener.enterEnrichWithClause(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitEnrichWithClause) { + listener.exitEnrichWithClause(this); + } + } +} + + +export class MvExpandCommandContext extends ParserRuleContext { + public MV_EXPAND(): TerminalNode { return this.getToken(esql_parser.MV_EXPAND, 0); } + public qualifiedNames(): QualifiedNamesContext { + return this.getRuleContext(0, QualifiedNamesContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_mvExpandCommand; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterMvExpandCommand) { + listener.enterMvExpandCommand(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitMvExpandCommand) { + listener.exitMvExpandCommand(this); + } + } +} + + +export class WhereCommandContext extends ParserRuleContext { + public WHERE(): TerminalNode { return this.getToken(esql_parser.WHERE, 0); } + public whereBooleanExpression(): WhereBooleanExpressionContext { + return this.getRuleContext(0, WhereBooleanExpressionContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_whereCommand; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterWhereCommand) { + listener.enterWhereCommand(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitWhereCommand) { + listener.exitWhereCommand(this); + } + } +} + + +export class WhereBooleanExpressionContext extends ParserRuleContext { + public _left: WhereBooleanExpressionContext; + public _operator: Token; + public _right: WhereBooleanExpressionContext; + public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } + public whereBooleanExpression(): WhereBooleanExpressionContext[]; + public whereBooleanExpression(i: number): WhereBooleanExpressionContext; + public whereBooleanExpression(i?: number): WhereBooleanExpressionContext | WhereBooleanExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(WhereBooleanExpressionContext); + } else { + return this.getRuleContext(i, WhereBooleanExpressionContext); + } + } + public valueExpression(): ValueExpressionContext[]; + public valueExpression(i: number): ValueExpressionContext; + public valueExpression(i?: number): ValueExpressionContext | ValueExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(ValueExpressionContext); + } else { + return this.getRuleContext(i, ValueExpressionContext); + } + } + public regexBooleanExpression(): RegexBooleanExpressionContext | undefined { + return this.tryGetRuleContext(0, RegexBooleanExpressionContext); + } + public AND(): TerminalNode | undefined { return this.tryGetToken(esql_parser.AND, 0); } + public OR(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OR, 0); } + public IN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.IN, 0); } + public LP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LP, 0); } + public RP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.RP, 0); } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } + } + public WHERE_FUNCTIONS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.WHERE_FUNCTIONS, 0); } + public qualifiedName(): QualifiedNameContext | undefined { + return this.tryGetRuleContext(0, QualifiedNameContext); + } + public functionExpressionArgument(): FunctionExpressionArgumentContext[]; + public functionExpressionArgument(i: number): FunctionExpressionArgumentContext; + public functionExpressionArgument(i?: number): FunctionExpressionArgumentContext | FunctionExpressionArgumentContext[] { + if (i === undefined) { + return this.getRuleContexts(FunctionExpressionArgumentContext); + } else { + return this.getRuleContext(i, FunctionExpressionArgumentContext); + } + } + public IS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.IS, 0); } + public NULL(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULL, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_whereBooleanExpression; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterWhereBooleanExpression) { + listener.enterWhereBooleanExpression(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitWhereBooleanExpression) { + listener.exitWhereBooleanExpression(this); + } + } +} + + +export class BooleanExpressionContext extends ParserRuleContext { + public _left: BooleanExpressionContext; + public _operator: Token; + public _right: BooleanExpressionContext; + public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } + public booleanExpression(): BooleanExpressionContext[]; + public booleanExpression(i: number): BooleanExpressionContext; + public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(BooleanExpressionContext); + } else { + return this.getRuleContext(i, BooleanExpressionContext); + } + } + public valueExpression(): ValueExpressionContext | undefined { + return this.tryGetRuleContext(0, ValueExpressionContext); + } + public AND(): TerminalNode | undefined { return this.tryGetToken(esql_parser.AND, 0); } + public OR(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OR, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_booleanExpression; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterBooleanExpression) { + listener.enterBooleanExpression(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitBooleanExpression) { + listener.exitBooleanExpression(this); + } + } } -export class SingleStatementContext extends ParserRuleContext { - public query(): QueryContext { - return this.getRuleContext(0, QueryContext); + +export class RegexBooleanExpressionContext extends ParserRuleContext { + public _kind: Token; + public _pattern: StringContext; + public valueExpression(): ValueExpressionContext { + return this.getRuleContext(0, ValueExpressionContext); } - public EOF(): TerminalNode { return this.getToken(esql_parser.EOF, 0); } + public LIKE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LIKE, 0); } + public string(): StringContext { + return this.getRuleContext(0, StringContext); + } + public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } + public RLIKE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.RLIKE, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_singleStatement; } + public get ruleIndex(): number { return esql_parser.RULE_regexBooleanExpression; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterSingleStatement) { - listener.enterSingleStatement(this); + if (listener.enterRegexBooleanExpression) { + listener.enterRegexBooleanExpression(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitSingleStatement) { - listener.exitSingleStatement(this); + if (listener.exitRegexBooleanExpression) { + listener.exitRegexBooleanExpression(this); } } } -export class QueryContext extends ParserRuleContext { +export class ValueExpressionContext extends ParserRuleContext { + public operatorExpression(): OperatorExpressionContext | undefined { + return this.tryGetRuleContext(0, OperatorExpressionContext); + } + public comparison(): ComparisonContext | undefined { + return this.tryGetRuleContext(0, ComparisonContext); + } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_query; } - public copyFrom(ctx: QueryContext): void { - super.copyFrom(ctx); + public get ruleIndex(): number { return esql_parser.RULE_valueExpression; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterValueExpression) { + listener.enterValueExpression(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitValueExpression) { + listener.exitValueExpression(this); + } } } -export class SingleCommandQueryContext extends QueryContext { - public sourceCommand(): SourceCommandContext { - return this.getRuleContext(0, SourceCommandContext); + + +export class ComparisonContext extends ParserRuleContext { + public _left: OperatorExpressionContext; + public _right: OperatorExpressionContext; + public comparisonOperator(): ComparisonOperatorContext { + return this.getRuleContext(0, ComparisonOperatorContext); } - constructor(ctx: QueryContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); + public operatorExpression(): OperatorExpressionContext[]; + public operatorExpression(i: number): OperatorExpressionContext; + public operatorExpression(i?: number): OperatorExpressionContext | OperatorExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(OperatorExpressionContext); + } else { + return this.getRuleContext(i, OperatorExpressionContext); + } } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_comparison; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterSingleCommandQuery) { - listener.enterSingleCommandQuery(this); + if (listener.enterComparison) { + listener.enterComparison(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitSingleCommandQuery) { - listener.exitSingleCommandQuery(this); + if (listener.exitComparison) { + listener.exitComparison(this); } } } -export class CompositeQueryContext extends QueryContext { - public query(): QueryContext { - return this.getRuleContext(0, QueryContext); + + +export class MathFnContext extends ParserRuleContext { + public functionIdentifier(): FunctionIdentifierContext { + return this.getRuleContext(0, FunctionIdentifierContext); } - public PIPE(): TerminalNode { return this.getToken(esql_parser.PIPE, 0); } - public processingCommand(): ProcessingCommandContext { - return this.getRuleContext(0, ProcessingCommandContext); + public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } + public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } + public functionExpressionArgument(): FunctionExpressionArgumentContext[]; + public functionExpressionArgument(i: number): FunctionExpressionArgumentContext; + public functionExpressionArgument(i?: number): FunctionExpressionArgumentContext | FunctionExpressionArgumentContext[] { + if (i === undefined) { + return this.getRuleContexts(FunctionExpressionArgumentContext); + } else { + return this.getRuleContext(i, FunctionExpressionArgumentContext); + } } - constructor(ctx: QueryContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); } // @Override + public get ruleIndex(): number { return esql_parser.RULE_mathFn; } + // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterCompositeQuery) { - listener.enterCompositeQuery(this); + if (listener.enterMathFn) { + listener.enterMathFn(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitCompositeQuery) { - listener.exitCompositeQuery(this); + if (listener.exitMathFn) { + listener.exitMathFn(this); + } + } +} + + +export class MathEvalFnContext extends ParserRuleContext { + public mathFunctionIdentifier(): MathFunctionIdentifierContext { + return this.getRuleContext(0, MathFunctionIdentifierContext); + } + public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } + public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } + public mathFunctionExpressionArgument(): MathFunctionExpressionArgumentContext[]; + public mathFunctionExpressionArgument(i: number): MathFunctionExpressionArgumentContext; + public mathFunctionExpressionArgument(i?: number): MathFunctionExpressionArgumentContext | MathFunctionExpressionArgumentContext[] { + if (i === undefined) { + return this.getRuleContexts(MathFunctionExpressionArgumentContext); + } else { + return this.getRuleContext(i, MathFunctionExpressionArgumentContext); + } + } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_mathEvalFn; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterMathEvalFn) { + listener.enterMathEvalFn(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitMathEvalFn) { + listener.exitMathEvalFn(this); + } + } +} + + +export class OperatorExpressionContext extends ParserRuleContext { + public _left: OperatorExpressionContext; + public _operator: Token; + public _right: OperatorExpressionContext; + public primaryExpression(): PrimaryExpressionContext | undefined { + return this.tryGetRuleContext(0, PrimaryExpressionContext); + } + public mathFn(): MathFnContext | undefined { + return this.tryGetRuleContext(0, MathFnContext); + } + public mathEvalFn(): MathEvalFnContext | undefined { + return this.tryGetRuleContext(0, MathEvalFnContext); + } + public operatorExpression(): OperatorExpressionContext[]; + public operatorExpression(i: number): OperatorExpressionContext; + public operatorExpression(i?: number): OperatorExpressionContext | OperatorExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(OperatorExpressionContext); + } else { + return this.getRuleContext(i, OperatorExpressionContext); + } + } + public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } + public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } + public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } + public SLASH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SLASH, 0); } + public PERCENT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PERCENT, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_operatorExpression; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterOperatorExpression) { + listener.enterOperatorExpression(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitOperatorExpression) { + listener.exitOperatorExpression(this); + } + } +} + + +export class PrimaryExpressionContext extends ParserRuleContext { + public constant(): ConstantContext | undefined { + return this.tryGetRuleContext(0, ConstantContext); + } + public qualifiedName(): QualifiedNameContext | undefined { + return this.tryGetRuleContext(0, QualifiedNameContext); + } + public LP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LP, 0); } + public booleanExpression(): BooleanExpressionContext[]; + public booleanExpression(i: number): BooleanExpressionContext; + public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(BooleanExpressionContext); + } else { + return this.getRuleContext(i, BooleanExpressionContext); + } + } + public RP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.RP, 0); } + public identifier(): IdentifierContext | undefined { + return this.tryGetRuleContext(0, IdentifierContext); + } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_primaryExpression; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterPrimaryExpression) { + listener.enterPrimaryExpression(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitPrimaryExpression) { + listener.exitPrimaryExpression(this); } } } -export class SourceCommandContext extends ParserRuleContext { - public explainCommand(): ExplainCommandContext | undefined { - return this.tryGetRuleContext(0, ExplainCommandContext); - } - public fromCommand(): FromCommandContext | undefined { - return this.tryGetRuleContext(0, FromCommandContext); - } - public rowCommand(): RowCommandContext | undefined { - return this.tryGetRuleContext(0, RowCommandContext); +export class RowCommandContext extends ParserRuleContext { + public ROW(): TerminalNode { return this.getToken(esql_parser.ROW, 0); } + public fields(): FieldsContext { + return this.getRuleContext(0, FieldsContext); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_sourceCommand; } + public get ruleIndex(): number { return esql_parser.RULE_rowCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterSourceCommand) { - listener.enterSourceCommand(this); + if (listener.enterRowCommand) { + listener.enterRowCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitSourceCommand) { - listener.exitSourceCommand(this); + if (listener.exitRowCommand) { + listener.exitRowCommand(this); } } } -export class ProcessingCommandContext extends ParserRuleContext { - public evalCommand(): EvalCommandContext | undefined { - return this.tryGetRuleContext(0, EvalCommandContext); - } - public limitCommand(): LimitCommandContext | undefined { - return this.tryGetRuleContext(0, LimitCommandContext); - } - public projectCommand(): ProjectCommandContext | undefined { - return this.tryGetRuleContext(0, ProjectCommandContext); - } - public sortCommand(): SortCommandContext | undefined { - return this.tryGetRuleContext(0, SortCommandContext); - } - public statsCommand(): StatsCommandContext | undefined { - return this.tryGetRuleContext(0, StatsCommandContext); +export class FieldsContext extends ParserRuleContext { + public field(): FieldContext[]; + public field(i: number): FieldContext; + public field(i?: number): FieldContext | FieldContext[] { + if (i === undefined) { + return this.getRuleContexts(FieldContext); + } else { + return this.getRuleContext(i, FieldContext); + } } - public whereCommand(): WhereCommandContext | undefined { - return this.tryGetRuleContext(0, WhereCommandContext); + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_processingCommand; } + public get ruleIndex(): number { return esql_parser.RULE_fields; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterProcessingCommand) { - listener.enterProcessingCommand(this); + if (listener.enterFields) { + listener.enterFields(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitProcessingCommand) { - listener.exitProcessingCommand(this); + if (listener.exitFields) { + listener.exitFields(this); } } } -export class WhereCommandContext extends ParserRuleContext { - public WHERE(): TerminalNode { return this.getToken(esql_parser.WHERE, 0); } +export class FieldContext extends ParserRuleContext { public booleanExpression(): BooleanExpressionContext { return this.getRuleContext(0, BooleanExpressionContext); } + public userVariable(): UserVariableContext | undefined { + return this.tryGetRuleContext(0, UserVariableContext); + } + public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_whereCommand; } + public get ruleIndex(): number { return esql_parser.RULE_field; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterWhereCommand) { - listener.enterWhereCommand(this); + if (listener.enterField) { + listener.enterField(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitWhereCommand) { - listener.exitWhereCommand(this); + if (listener.exitField) { + listener.exitField(this); } } } -export class BooleanExpressionContext extends ParserRuleContext { - public _left: BooleanExpressionContext; - public _operator: Token; - public _right: BooleanExpressionContext; - public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } - public booleanExpression(): BooleanExpressionContext[]; - public booleanExpression(i: number): BooleanExpressionContext; - public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(BooleanExpressionContext); - } else { - return this.getRuleContext(i, BooleanExpressionContext); - } - } - public valueExpression(): ValueExpressionContext | undefined { - return this.tryGetRuleContext(0, ValueExpressionContext); - } - public AND(): TerminalNode | undefined { return this.tryGetToken(esql_parser.AND, 0); } - public OR(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OR, 0); } +export class EnrichFieldIdentifierContext extends ParserRuleContext { + public ENR_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_UNQUOTED_IDENTIFIER, 0); } + public ENR_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_QUOTED_IDENTIFIER, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_booleanExpression; } + public get ruleIndex(): number { return esql_parser.RULE_enrichFieldIdentifier; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterBooleanExpression) { - listener.enterBooleanExpression(this); + if (listener.enterEnrichFieldIdentifier) { + listener.enterEnrichFieldIdentifier(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitBooleanExpression) { - listener.exitBooleanExpression(this); + if (listener.exitEnrichFieldIdentifier) { + listener.exitEnrichFieldIdentifier(this); } } } -export class ValueExpressionContext extends ParserRuleContext { - public operatorExpression(): OperatorExpressionContext | undefined { - return this.tryGetRuleContext(0, OperatorExpressionContext); - } - public comparison(): ComparisonContext | undefined { - return this.tryGetRuleContext(0, ComparisonContext); +export class UserVariableContext extends ParserRuleContext { + public identifier(): IdentifierContext { + return this.getRuleContext(0, IdentifierContext); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_valueExpression; } + public get ruleIndex(): number { return esql_parser.RULE_userVariable; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterValueExpression) { - listener.enterValueExpression(this); + if (listener.enterUserVariable) { + listener.enterUserVariable(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitValueExpression) { - listener.exitValueExpression(this); + if (listener.exitUserVariable) { + listener.exitUserVariable(this); } } } -export class ComparisonContext extends ParserRuleContext { - public _left: OperatorExpressionContext; - public _right: OperatorExpressionContext; - public comparisonOperator(): ComparisonOperatorContext { - return this.getRuleContext(0, ComparisonOperatorContext); +export class FromCommandContext extends ParserRuleContext { + public FROM(): TerminalNode { return this.getToken(esql_parser.FROM, 0); } + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(SourceIdentifierContext); + } else { + return this.getRuleContext(i, SourceIdentifierContext); + } } - public operatorExpression(): OperatorExpressionContext[]; - public operatorExpression(i: number): OperatorExpressionContext; - public operatorExpression(i?: number): OperatorExpressionContext | OperatorExpressionContext[] { + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { if (i === undefined) { - return this.getRuleContexts(OperatorExpressionContext); + return this.getTokens(esql_parser.COMMA); } else { - return this.getRuleContext(i, OperatorExpressionContext); + return this.getToken(esql_parser.COMMA, i); } } + public metadata(): MetadataContext | undefined { + return this.tryGetRuleContext(0, MetadataContext); + } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_comparison; } + public get ruleIndex(): number { return esql_parser.RULE_fromCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterComparison) { - listener.enterComparison(this); + if (listener.enterFromCommand) { + listener.enterFromCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitComparison) { - listener.exitComparison(this); + if (listener.exitFromCommand) { + listener.exitFromCommand(this); } } } -export class MathFnContext extends ParserRuleContext { - public functionIdentifier(): FunctionIdentifierContext { - return this.getRuleContext(0, FunctionIdentifierContext); - } - public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } - public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } - public functionExpressionArgument(): FunctionExpressionArgumentContext[]; - public functionExpressionArgument(i: number): FunctionExpressionArgumentContext; - public functionExpressionArgument(i?: number): FunctionExpressionArgumentContext | FunctionExpressionArgumentContext[] { +export class MetadataContext extends ParserRuleContext { + public OPENING_BRACKET(): TerminalNode { return this.getToken(esql_parser.OPENING_BRACKET, 0); } + public METADATA(): TerminalNode { return this.getToken(esql_parser.METADATA, 0); } + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { if (i === undefined) { - return this.getRuleContexts(FunctionExpressionArgumentContext); + return this.getRuleContexts(SourceIdentifierContext); } else { - return this.getRuleContext(i, FunctionExpressionArgumentContext); + return this.getRuleContext(i, SourceIdentifierContext); } } + public CLOSING_BRACKET(): TerminalNode { return this.getToken(esql_parser.CLOSING_BRACKET, 0); } public COMMA(): TerminalNode[]; public COMMA(i: number): TerminalNode; public COMMA(i?: number): TerminalNode | TerminalNode[] { @@ -2306,241 +4413,236 @@ export class MathFnContext extends ParserRuleContext { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mathFn; } + public get ruleIndex(): number { return esql_parser.RULE_metadata; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMathFn) { - listener.enterMathFn(this); + if (listener.enterMetadata) { + listener.enterMetadata(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMathFn) { - listener.exitMathFn(this); + if (listener.exitMetadata) { + listener.exitMetadata(this); } } } -export class OperatorExpressionContext extends ParserRuleContext { - public _left: OperatorExpressionContext; - public _operator: Token; - public _right: OperatorExpressionContext; - public primaryExpression(): PrimaryExpressionContext | undefined { - return this.tryGetRuleContext(0, PrimaryExpressionContext); - } - public mathFn(): MathFnContext | undefined { - return this.tryGetRuleContext(0, MathFnContext); - } - public operatorExpression(): OperatorExpressionContext[]; - public operatorExpression(i: number): OperatorExpressionContext; - public operatorExpression(i?: number): OperatorExpressionContext | OperatorExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(OperatorExpressionContext); - } else { - return this.getRuleContext(i, OperatorExpressionContext); - } +export class EvalCommandContext extends ParserRuleContext { + public EVAL(): TerminalNode { return this.getToken(esql_parser.EVAL, 0); } + public fields(): FieldsContext { + return this.getRuleContext(0, FieldsContext); } - public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } - public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } - public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } - public SLASH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SLASH, 0); } - public PERCENT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PERCENT, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_operatorExpression; } + public get ruleIndex(): number { return esql_parser.RULE_evalCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterOperatorExpression) { - listener.enterOperatorExpression(this); + if (listener.enterEvalCommand) { + listener.enterEvalCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitOperatorExpression) { - listener.exitOperatorExpression(this); + if (listener.exitEvalCommand) { + listener.exitEvalCommand(this); } } } -export class PrimaryExpressionContext extends ParserRuleContext { - public constant(): ConstantContext | undefined { - return this.tryGetRuleContext(0, ConstantContext); - } - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); - } - public LP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LP, 0); } - public booleanExpression(): BooleanExpressionContext[]; - public booleanExpression(i: number): BooleanExpressionContext; - public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(BooleanExpressionContext); - } else { - return this.getRuleContext(i, BooleanExpressionContext); - } - } - public RP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.RP, 0); } - public identifier(): IdentifierContext | undefined { - return this.tryGetRuleContext(0, IdentifierContext); +export class StatsCommandContext extends ParserRuleContext { + public STATS(): TerminalNode { return this.getToken(esql_parser.STATS, 0); } + public fields(): FieldsContext | undefined { + return this.tryGetRuleContext(0, FieldsContext); } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.COMMA); - } else { - return this.getToken(esql_parser.COMMA, i); - } + public BY(): TerminalNode | undefined { return this.tryGetToken(esql_parser.BY, 0); } + public qualifiedNames(): QualifiedNamesContext | undefined { + return this.tryGetRuleContext(0, QualifiedNamesContext); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_primaryExpression; } + public get ruleIndex(): number { return esql_parser.RULE_statsCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterPrimaryExpression) { - listener.enterPrimaryExpression(this); + if (listener.enterStatsCommand) { + listener.enterStatsCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitPrimaryExpression) { - listener.exitPrimaryExpression(this); + if (listener.exitStatsCommand) { + listener.exitStatsCommand(this); } } } -export class RowCommandContext extends ParserRuleContext { - public ROW(): TerminalNode { return this.getToken(esql_parser.ROW, 0); } - public fields(): FieldsContext { - return this.getRuleContext(0, FieldsContext); - } +export class SourceIdentifierContext extends ParserRuleContext { + public SRC_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_UNQUOTED_IDENTIFIER, 0); } + public SRC_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_QUOTED_IDENTIFIER, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_rowCommand; } + public get ruleIndex(): number { return esql_parser.RULE_sourceIdentifier; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterRowCommand) { - listener.enterRowCommand(this); + if (listener.enterSourceIdentifier) { + listener.enterSourceIdentifier(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitRowCommand) { - listener.exitRowCommand(this); + if (listener.exitSourceIdentifier) { + listener.exitSourceIdentifier(this); } } } -export class FieldsContext extends ParserRuleContext { - public field(): FieldContext[]; - public field(i: number): FieldContext; - public field(i?: number): FieldContext | FieldContext[] { - if (i === undefined) { - return this.getRuleContexts(FieldContext); - } else { - return this.getRuleContext(i, FieldContext); +export class EnrichIdentifierContext extends ParserRuleContext { + public ENR_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_UNQUOTED_IDENTIFIER, 0); } + public ENR_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_QUOTED_IDENTIFIER, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_enrichIdentifier; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterEnrichIdentifier) { + listener.enterEnrichIdentifier(this); } } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.COMMA); - } else { - return this.getToken(esql_parser.COMMA, i); + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitEnrichIdentifier) { + listener.exitEnrichIdentifier(this); } } +} + + +export class FunctionExpressionArgumentContext extends ParserRuleContext { + public qualifiedName(): QualifiedNameContext | undefined { + return this.tryGetRuleContext(0, QualifiedNameContext); + } + public string(): StringContext | undefined { + return this.tryGetRuleContext(0, StringContext); + } + public number(): NumberContext | undefined { + return this.tryGetRuleContext(0, NumberContext); + } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_fields; } + public get ruleIndex(): number { return esql_parser.RULE_functionExpressionArgument; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterFields) { - listener.enterFields(this); + if (listener.enterFunctionExpressionArgument) { + listener.enterFunctionExpressionArgument(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitFields) { - listener.exitFields(this); + if (listener.exitFunctionExpressionArgument) { + listener.exitFunctionExpressionArgument(this); } } } -export class FieldContext extends ParserRuleContext { - public booleanExpression(): BooleanExpressionContext { - return this.getRuleContext(0, BooleanExpressionContext); +export class MathFunctionExpressionArgumentContext extends ParserRuleContext { + public qualifiedName(): QualifiedNameContext | undefined { + return this.tryGetRuleContext(0, QualifiedNameContext); } - public userVariable(): UserVariableContext | undefined { - return this.tryGetRuleContext(0, UserVariableContext); + public string(): StringContext | undefined { + return this.tryGetRuleContext(0, StringContext); + } + public number(): NumberContext | undefined { + return this.tryGetRuleContext(0, NumberContext); + } + public operatorExpression(): OperatorExpressionContext | undefined { + return this.tryGetRuleContext(0, OperatorExpressionContext); + } + public DATE_LITERAL(): TerminalNode | undefined { return this.tryGetToken(esql_parser.DATE_LITERAL, 0); } + public comparison(): ComparisonContext | undefined { + return this.tryGetRuleContext(0, ComparisonContext); } - public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_field; } + public get ruleIndex(): number { return esql_parser.RULE_mathFunctionExpressionArgument; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterField) { - listener.enterField(this); + if (listener.enterMathFunctionExpressionArgument) { + listener.enterMathFunctionExpressionArgument(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitField) { - listener.exitField(this); + if (listener.exitMathFunctionExpressionArgument) { + listener.exitMathFunctionExpressionArgument(this); } } } -export class UserVariableContext extends ParserRuleContext { - public identifier(): IdentifierContext { - return this.getRuleContext(0, IdentifierContext); +export class QualifiedNameContext extends ParserRuleContext { + public identifier(): IdentifierContext[]; + public identifier(i: number): IdentifierContext; + public identifier(i?: number): IdentifierContext | IdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(IdentifierContext); + } else { + return this.getRuleContext(i, IdentifierContext); + } + } + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.DOT); + } else { + return this.getToken(esql_parser.DOT, i); + } } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_userVariable; } + public get ruleIndex(): number { return esql_parser.RULE_qualifiedName; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterUserVariable) { - listener.enterUserVariable(this); + if (listener.enterQualifiedName) { + listener.enterQualifiedName(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitUserVariable) { - listener.exitUserVariable(this); + if (listener.exitQualifiedName) { + listener.exitQualifiedName(this); } } } -export class FromCommandContext extends ParserRuleContext { - public FROM(): TerminalNode { return this.getToken(esql_parser.FROM, 0); } - public sourceIdentifier(): SourceIdentifierContext[]; - public sourceIdentifier(i: number): SourceIdentifierContext; - public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { +export class QualifiedNamesContext extends ParserRuleContext { + public qualifiedName(): QualifiedNameContext[]; + public qualifiedName(i: number): QualifiedNameContext; + public qualifiedName(i?: number): QualifiedNameContext | QualifiedNameContext[] { if (i === undefined) { - return this.getRuleContexts(SourceIdentifierContext); + return this.getRuleContexts(QualifiedNameContext); } else { - return this.getRuleContext(i, SourceIdentifierContext); + return this.getRuleContext(i, QualifiedNameContext); } } public COMMA(): TerminalNode[]; @@ -2556,173 +4658,209 @@ export class FromCommandContext extends ParserRuleContext { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_fromCommand; } + public get ruleIndex(): number { return esql_parser.RULE_qualifiedNames; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterFromCommand) { - listener.enterFromCommand(this); + if (listener.enterQualifiedNames) { + listener.enterQualifiedNames(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitFromCommand) { - listener.exitFromCommand(this); + if (listener.exitQualifiedNames) { + listener.exitQualifiedNames(this); } } } -export class EvalCommandContext extends ParserRuleContext { - public EVAL(): TerminalNode { return this.getToken(esql_parser.EVAL, 0); } - public fields(): FieldsContext { - return this.getRuleContext(0, FieldsContext); - } +export class IdentifierContext extends ParserRuleContext { + public UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.UNQUOTED_IDENTIFIER, 0); } + public QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.QUOTED_IDENTIFIER, 0); } + public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_evalCommand; } + public get ruleIndex(): number { return esql_parser.RULE_identifier; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterEvalCommand) { - listener.enterEvalCommand(this); + if (listener.enterIdentifier) { + listener.enterIdentifier(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitEvalCommand) { - listener.exitEvalCommand(this); + if (listener.exitIdentifier) { + listener.exitIdentifier(this); } } } -export class StatsCommandContext extends ParserRuleContext { - public STATS(): TerminalNode { return this.getToken(esql_parser.STATS, 0); } - public fields(): FieldsContext { - return this.getRuleContext(0, FieldsContext); - } - public BY(): TerminalNode | undefined { return this.tryGetToken(esql_parser.BY, 0); } - public qualifiedNames(): QualifiedNamesContext | undefined { - return this.tryGetRuleContext(0, QualifiedNamesContext); - } +export class MathFunctionIdentifierContext extends ParserRuleContext { + public MATH_FUNCTION(): TerminalNode { return this.getToken(esql_parser.MATH_FUNCTION, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_statsCommand; } + public get ruleIndex(): number { return esql_parser.RULE_mathFunctionIdentifier; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterStatsCommand) { - listener.enterStatsCommand(this); + if (listener.enterMathFunctionIdentifier) { + listener.enterMathFunctionIdentifier(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitStatsCommand) { - listener.exitStatsCommand(this); + if (listener.exitMathFunctionIdentifier) { + listener.exitMathFunctionIdentifier(this); } } } -export class SourceIdentifierContext extends ParserRuleContext { - public SRC_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_UNQUOTED_IDENTIFIER, 0); } - public SRC_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_QUOTED_IDENTIFIER, 0); } +export class FunctionIdentifierContext extends ParserRuleContext { + public UNARY_FUNCTION(): TerminalNode { return this.getToken(esql_parser.UNARY_FUNCTION, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_sourceIdentifier; } + public get ruleIndex(): number { return esql_parser.RULE_functionIdentifier; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterSourceIdentifier) { - listener.enterSourceIdentifier(this); + if (listener.enterFunctionIdentifier) { + listener.enterFunctionIdentifier(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitSourceIdentifier) { - listener.exitSourceIdentifier(this); + if (listener.exitFunctionIdentifier) { + listener.exitFunctionIdentifier(this); } } } -export class FunctionExpressionArgumentContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); +export class ConstantContext extends ParserRuleContext { + public NULL(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULL, 0); } + public numericValue(): NumericValueContext[]; + public numericValue(i: number): NumericValueContext; + public numericValue(i?: number): NumericValueContext | NumericValueContext[] { + if (i === undefined) { + return this.getRuleContexts(NumericValueContext); + } else { + return this.getRuleContext(i, NumericValueContext); + } } - public string(): StringContext | undefined { - return this.tryGetRuleContext(0, StringContext); + public booleanValue(): BooleanValueContext[]; + public booleanValue(i: number): BooleanValueContext; + public booleanValue(i?: number): BooleanValueContext | BooleanValueContext[] { + if (i === undefined) { + return this.getRuleContexts(BooleanValueContext); + } else { + return this.getRuleContext(i, BooleanValueContext); + } + } + public string(): StringContext[]; + public string(i: number): StringContext; + public string(i?: number): StringContext | StringContext[] { + if (i === undefined) { + return this.getRuleContexts(StringContext); + } else { + return this.getRuleContext(i, StringContext); + } + } + public OPENING_BRACKET(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OPENING_BRACKET, 0); } + public CLOSING_BRACKET(): TerminalNode | undefined { return this.tryGetToken(esql_parser.CLOSING_BRACKET, 0); } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_functionExpressionArgument; } + public get ruleIndex(): number { return esql_parser.RULE_constant; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterFunctionExpressionArgument) { - listener.enterFunctionExpressionArgument(this); + if (listener.enterConstant) { + listener.enterConstant(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitFunctionExpressionArgument) { - listener.exitFunctionExpressionArgument(this); + if (listener.exitConstant) { + listener.exitConstant(this); } } } -export class QualifiedNameContext extends ParserRuleContext { - public identifier(): IdentifierContext[]; - public identifier(i: number): IdentifierContext; - public identifier(i?: number): IdentifierContext | IdentifierContext[] { - if (i === undefined) { - return this.getRuleContexts(IdentifierContext); - } else { - return this.getRuleContext(i, IdentifierContext); +export class NumericValueContext extends ParserRuleContext { + public decimalValue(): DecimalValueContext | undefined { + return this.tryGetRuleContext(0, DecimalValueContext); + } + public integerValue(): IntegerValueContext | undefined { + return this.tryGetRuleContext(0, IntegerValueContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_numericValue; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterNumericValue) { + listener.enterNumericValue(this); } } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.DOT); - } else { - return this.getToken(esql_parser.DOT, i); + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitNumericValue) { + listener.exitNumericValue(this); } } +} + + +export class LimitCommandContext extends ParserRuleContext { + public LIMIT(): TerminalNode { return this.getToken(esql_parser.LIMIT, 0); } + public INTEGER_LITERAL(): TerminalNode { return this.getToken(esql_parser.INTEGER_LITERAL, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_qualifiedName; } + public get ruleIndex(): number { return esql_parser.RULE_limitCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterQualifiedName) { - listener.enterQualifiedName(this); + if (listener.enterLimitCommand) { + listener.enterLimitCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitQualifiedName) { - listener.exitQualifiedName(this); + if (listener.exitLimitCommand) { + listener.exitLimitCommand(this); } } } -export class QualifiedNamesContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext[]; - public qualifiedName(i: number): QualifiedNameContext; - public qualifiedName(i?: number): QualifiedNameContext | QualifiedNameContext[] { +export class SortCommandContext extends ParserRuleContext { + public SORT(): TerminalNode { return this.getToken(esql_parser.SORT, 0); } + public orderExpression(): OrderExpressionContext[]; + public orderExpression(i: number): OrderExpressionContext; + public orderExpression(i?: number): OrderExpressionContext | OrderExpressionContext[] { if (i === undefined) { - return this.getRuleContexts(QualifiedNameContext); + return this.getRuleContexts(OrderExpressionContext); } else { - return this.getRuleContext(i, QualifiedNameContext); + return this.getRuleContext(i, OrderExpressionContext); } } public COMMA(): TerminalNode[]; @@ -2738,260 +4876,298 @@ export class QualifiedNamesContext extends ParserRuleContext { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_qualifiedNames; } + public get ruleIndex(): number { return esql_parser.RULE_sortCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterQualifiedNames) { - listener.enterQualifiedNames(this); + if (listener.enterSortCommand) { + listener.enterSortCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitQualifiedNames) { - listener.exitQualifiedNames(this); + if (listener.exitSortCommand) { + listener.exitSortCommand(this); } } } -export class IdentifierContext extends ParserRuleContext { - public UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.UNQUOTED_IDENTIFIER, 0); } - public QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.QUOTED_IDENTIFIER, 0); } +export class OrderExpressionContext extends ParserRuleContext { + public booleanExpression(): BooleanExpressionContext { + return this.getRuleContext(0, BooleanExpressionContext); + } + public ORDERING(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ORDERING, 0); } + public NULLS_ORDERING(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS_ORDERING, 0); } + public NULLS_ORDERING_DIRECTION(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS_ORDERING_DIRECTION, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_identifier; } + public get ruleIndex(): number { return esql_parser.RULE_orderExpression; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterIdentifier) { - listener.enterIdentifier(this); + if (listener.enterOrderExpression) { + listener.enterOrderExpression(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitIdentifier) { - listener.exitIdentifier(this); + if (listener.exitOrderExpression) { + listener.exitOrderExpression(this); } } } -export class FunctionIdentifierContext extends ParserRuleContext { - public UNARY_FUNCTION(): TerminalNode { return this.getToken(esql_parser.UNARY_FUNCTION, 0); } +export class ProjectCommandContext extends ParserRuleContext { + public PROJECT(): TerminalNode { return this.getToken(esql_parser.PROJECT, 0); } + public qualifiedNames(): QualifiedNamesContext { + return this.getRuleContext(0, QualifiedNamesContext); + } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_functionIdentifier; } + public get ruleIndex(): number { return esql_parser.RULE_projectCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterFunctionIdentifier) { - listener.enterFunctionIdentifier(this); + if (listener.enterProjectCommand) { + listener.enterProjectCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitFunctionIdentifier) { - listener.exitFunctionIdentifier(this); + if (listener.exitProjectCommand) { + listener.exitProjectCommand(this); } } } -export class ConstantContext extends ParserRuleContext { +export class KeepCommandContext extends ParserRuleContext { + public KEEP(): TerminalNode { return this.getToken(esql_parser.KEEP, 0); } + public qualifiedNames(): QualifiedNamesContext { + return this.getRuleContext(0, QualifiedNamesContext); + } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_constant; } - public copyFrom(ctx: ConstantContext): void { - super.copyFrom(ctx); - } -} -export class NullLiteralContext extends ConstantContext { - public NULL(): TerminalNode { return this.getToken(esql_parser.NULL, 0); } - constructor(ctx: ConstantContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); - } + public get ruleIndex(): number { return esql_parser.RULE_keepCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterNullLiteral) { - listener.enterNullLiteral(this); + if (listener.enterKeepCommand) { + listener.enterKeepCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitNullLiteral) { - listener.exitNullLiteral(this); + if (listener.exitKeepCommand) { + listener.exitKeepCommand(this); } } } -export class NumericLiteralContext extends ConstantContext { - public number(): NumberContext { - return this.getRuleContext(0, NumberContext); + + +export class DropCommandContext extends ParserRuleContext { + public DROP(): TerminalNode { return this.getToken(esql_parser.DROP, 0); } + public qualifiedNames(): QualifiedNamesContext { + return this.getRuleContext(0, QualifiedNamesContext); } - constructor(ctx: ConstantContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); } // @Override + public get ruleIndex(): number { return esql_parser.RULE_dropCommand; } + // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterNumericLiteral) { - listener.enterNumericLiteral(this); + if (listener.enterDropCommand) { + listener.enterDropCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitNumericLiteral) { - listener.exitNumericLiteral(this); + if (listener.exitDropCommand) { + listener.exitDropCommand(this); } } } -export class BooleanLiteralContext extends ConstantContext { - public booleanValue(): BooleanValueContext { - return this.getRuleContext(0, BooleanValueContext); + + +export class RenameVariableContext extends ParserRuleContext { + public identifier(): IdentifierContext[]; + public identifier(i: number): IdentifierContext; + public identifier(i?: number): IdentifierContext | IdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(IdentifierContext); + } else { + return this.getRuleContext(i, IdentifierContext); + } } - constructor(ctx: ConstantContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); + public DOT(): TerminalNode[]; + public DOT(i: number): TerminalNode; + public DOT(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.DOT); + } else { + return this.getToken(esql_parser.DOT, i); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); } // @Override + public get ruleIndex(): number { return esql_parser.RULE_renameVariable; } + // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterBooleanLiteral) { - listener.enterBooleanLiteral(this); + if (listener.enterRenameVariable) { + listener.enterRenameVariable(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitBooleanLiteral) { - listener.exitBooleanLiteral(this); + if (listener.exitRenameVariable) { + listener.exitRenameVariable(this); } } } -export class StringLiteralContext extends ConstantContext { - public string(): StringContext { - return this.getRuleContext(0, StringContext); + + +export class RenameCommandContext extends ParserRuleContext { + public RENAME(): TerminalNode { return this.getToken(esql_parser.RENAME, 0); } + public renameClause(): RenameClauseContext[]; + public renameClause(i: number): RenameClauseContext; + public renameClause(i?: number): RenameClauseContext | RenameClauseContext[] { + if (i === undefined) { + return this.getRuleContexts(RenameClauseContext); + } else { + return this.getRuleContext(i, RenameClauseContext); + } } - constructor(ctx: ConstantContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_renameCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterStringLiteral) { - listener.enterStringLiteral(this); + if (listener.enterRenameCommand) { + listener.enterRenameCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitStringLiteral) { - listener.exitStringLiteral(this); + if (listener.exitRenameCommand) { + listener.exitRenameCommand(this); } } } -export class LimitCommandContext extends ParserRuleContext { - public LIMIT(): TerminalNode { return this.getToken(esql_parser.LIMIT, 0); } - public INTEGER_LITERAL(): TerminalNode { return this.getToken(esql_parser.INTEGER_LITERAL, 0); } +export class RenameClauseContext extends ParserRuleContext { + public qualifiedName(): QualifiedNameContext { + return this.getRuleContext(0, QualifiedNameContext); + } + public AS(): TerminalNode { return this.getToken(esql_parser.AS, 0); } + public renameVariable(): RenameVariableContext { + return this.getRuleContext(0, RenameVariableContext); + } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_limitCommand; } + public get ruleIndex(): number { return esql_parser.RULE_renameClause; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterLimitCommand) { - listener.enterLimitCommand(this); + if (listener.enterRenameClause) { + listener.enterRenameClause(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitLimitCommand) { - listener.exitLimitCommand(this); + if (listener.exitRenameClause) { + listener.exitRenameClause(this); } } } -export class SortCommandContext extends ParserRuleContext { - public SORT(): TerminalNode { return this.getToken(esql_parser.SORT, 0); } - public orderExpression(): OrderExpressionContext[]; - public orderExpression(i: number): OrderExpressionContext; - public orderExpression(i?: number): OrderExpressionContext | OrderExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(OrderExpressionContext); - } else { - return this.getRuleContext(i, OrderExpressionContext); - } +export class DissectCommandContext extends ParserRuleContext { + public DISSECT(): TerminalNode { return this.getToken(esql_parser.DISSECT, 0); } + public qualifiedNames(): QualifiedNamesContext { + return this.getRuleContext(0, QualifiedNamesContext); } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.COMMA); - } else { - return this.getToken(esql_parser.COMMA, i); - } + public string(): StringContext { + return this.getRuleContext(0, StringContext); + } + public commandOptions(): CommandOptionsContext | undefined { + return this.tryGetRuleContext(0, CommandOptionsContext); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_sortCommand; } + public get ruleIndex(): number { return esql_parser.RULE_dissectCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterSortCommand) { - listener.enterSortCommand(this); + if (listener.enterDissectCommand) { + listener.enterDissectCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitSortCommand) { - listener.exitSortCommand(this); + if (listener.exitDissectCommand) { + listener.exitDissectCommand(this); } } } -export class OrderExpressionContext extends ParserRuleContext { - public booleanExpression(): BooleanExpressionContext { - return this.getRuleContext(0, BooleanExpressionContext); +export class GrokCommandContext extends ParserRuleContext { + public GROK(): TerminalNode { return this.getToken(esql_parser.GROK, 0); } + public qualifiedNames(): QualifiedNamesContext { + return this.getRuleContext(0, QualifiedNamesContext); + } + public string(): StringContext { + return this.getRuleContext(0, StringContext); } - public ORDERING(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ORDERING, 0); } - public NULLS_ORDERING(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS_ORDERING, 0); } - public NULLS_ORDERING_DIRECTION(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS_ORDERING_DIRECTION, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_orderExpression; } + public get ruleIndex(): number { return esql_parser.RULE_grokCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterOrderExpression) { - listener.enterOrderExpression(this); + if (listener.enterGrokCommand) { + listener.enterGrokCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitOrderExpression) { - listener.exitOrderExpression(this); + if (listener.exitGrokCommand) { + listener.exitGrokCommand(this); } } } -export class ProjectCommandContext extends ParserRuleContext { - public PROJECT(): TerminalNode { return this.getToken(esql_parser.PROJECT, 0); } - public projectClause(): ProjectClauseContext[]; - public projectClause(i: number): ProjectClauseContext; - public projectClause(i?: number): ProjectClauseContext | ProjectClauseContext[] { +export class CommandOptionsContext extends ParserRuleContext { + public commandOption(): CommandOptionContext[]; + public commandOption(i: number): CommandOptionContext; + public commandOption(i?: number): CommandOptionContext | CommandOptionContext[] { if (i === undefined) { - return this.getRuleContexts(ProjectClauseContext); + return this.getRuleContexts(CommandOptionContext); } else { - return this.getRuleContext(i, ProjectClauseContext); + return this.getRuleContext(i, CommandOptionContext); } } public COMMA(): TerminalNode[]; @@ -3007,50 +5183,45 @@ export class ProjectCommandContext extends ParserRuleContext { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_projectCommand; } + public get ruleIndex(): number { return esql_parser.RULE_commandOptions; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterProjectCommand) { - listener.enterProjectCommand(this); + if (listener.enterCommandOptions) { + listener.enterCommandOptions(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitProjectCommand) { - listener.exitProjectCommand(this); + if (listener.exitCommandOptions) { + listener.exitCommandOptions(this); } } } -export class ProjectClauseContext extends ParserRuleContext { - public _newName: SourceIdentifierContext; - public _oldName: SourceIdentifierContext; - public sourceIdentifier(): SourceIdentifierContext[]; - public sourceIdentifier(i: number): SourceIdentifierContext; - public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { - if (i === undefined) { - return this.getRuleContexts(SourceIdentifierContext); - } else { - return this.getRuleContext(i, SourceIdentifierContext); - } +export class CommandOptionContext extends ParserRuleContext { + public identifier(): IdentifierContext { + return this.getRuleContext(0, IdentifierContext); + } + public ASSIGN(): TerminalNode { return this.getToken(esql_parser.ASSIGN, 0); } + public constant(): ConstantContext { + return this.getRuleContext(0, ConstantContext); } - public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_projectClause; } + public get ruleIndex(): number { return esql_parser.RULE_commandOption; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterProjectClause) { - listener.enterProjectClause(this); + if (listener.enterCommandOption) { + listener.enterCommandOption(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitProjectClause) { - listener.exitProjectClause(this); + if (listener.exitCommandOption) { + listener.exitCommandOption(this); } } } @@ -3128,6 +5299,50 @@ export class IntegerLiteralContext extends NumberContext { } +export class DecimalValueContext extends ParserRuleContext { + public DECIMAL_LITERAL(): TerminalNode { return this.getToken(esql_parser.DECIMAL_LITERAL, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_decimalValue; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterDecimalValue) { + listener.enterDecimalValue(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitDecimalValue) { + listener.exitDecimalValue(this); + } + } +} + + +export class IntegerValueContext extends ParserRuleContext { + public INTEGER_LITERAL(): TerminalNode { return this.getToken(esql_parser.INTEGER_LITERAL, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_integerValue; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterIntegerValue) { + listener.enterIntegerValue(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitIntegerValue) { + listener.exitIntegerValue(this); + } + } +} + + export class StringContext extends ParserRuleContext { public STRING(): TerminalNode { return this.getToken(esql_parser.STRING, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { @@ -3223,3 +5438,27 @@ export class SubqueryExpressionContext extends ParserRuleContext { } +export class ShowCommandContext extends ParserRuleContext { + public SHOW(): TerminalNode { return this.getToken(esql_parser.SHOW, 0); } + public INFO(): TerminalNode | undefined { return this.tryGetToken(esql_parser.INFO, 0); } + public FUNCTIONS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.FUNCTIONS, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_showCommand; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterShowCommand) { + listener.enterShowCommand(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitShowCommand) { + listener.exitShowCommand(this); + } + } +} + + diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts b/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts index 2b943a8bcff45..99a91b0bd84a3 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts @@ -4,10 +4,6 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; -import { NullLiteralContext } from "./esql_parser"; -import { NumericLiteralContext } from "./esql_parser"; -import { BooleanLiteralContext } from "./esql_parser"; -import { StringLiteralContext } from "./esql_parser"; import { DecimalLiteralContext } from "./esql_parser"; import { IntegerLiteralContext } from "./esql_parser"; import { SingleCommandQueryContext } from "./esql_parser"; @@ -16,38 +12,61 @@ import { SingleStatementContext } from "./esql_parser"; import { QueryContext } from "./esql_parser"; import { SourceCommandContext } from "./esql_parser"; import { ProcessingCommandContext } from "./esql_parser"; +import { EnrichCommandContext } from "./esql_parser"; +import { EnrichWithClauseContext } from "./esql_parser"; +import { MvExpandCommandContext } from "./esql_parser"; import { WhereCommandContext } from "./esql_parser"; +import { WhereBooleanExpressionContext } from "./esql_parser"; import { BooleanExpressionContext } from "./esql_parser"; +import { RegexBooleanExpressionContext } from "./esql_parser"; import { ValueExpressionContext } from "./esql_parser"; import { ComparisonContext } from "./esql_parser"; import { MathFnContext } from "./esql_parser"; +import { MathEvalFnContext } from "./esql_parser"; import { OperatorExpressionContext } from "./esql_parser"; import { PrimaryExpressionContext } from "./esql_parser"; import { RowCommandContext } from "./esql_parser"; import { FieldsContext } from "./esql_parser"; import { FieldContext } from "./esql_parser"; +import { EnrichFieldIdentifierContext } from "./esql_parser"; import { UserVariableContext } from "./esql_parser"; import { FromCommandContext } from "./esql_parser"; +import { MetadataContext } from "./esql_parser"; import { EvalCommandContext } from "./esql_parser"; import { StatsCommandContext } from "./esql_parser"; import { SourceIdentifierContext } from "./esql_parser"; +import { EnrichIdentifierContext } from "./esql_parser"; import { FunctionExpressionArgumentContext } from "./esql_parser"; +import { MathFunctionExpressionArgumentContext } from "./esql_parser"; import { QualifiedNameContext } from "./esql_parser"; import { QualifiedNamesContext } from "./esql_parser"; import { IdentifierContext } from "./esql_parser"; +import { MathFunctionIdentifierContext } from "./esql_parser"; import { FunctionIdentifierContext } from "./esql_parser"; import { ConstantContext } from "./esql_parser"; +import { NumericValueContext } from "./esql_parser"; import { LimitCommandContext } from "./esql_parser"; import { SortCommandContext } from "./esql_parser"; import { OrderExpressionContext } from "./esql_parser"; import { ProjectCommandContext } from "./esql_parser"; -import { ProjectClauseContext } from "./esql_parser"; +import { KeepCommandContext } from "./esql_parser"; +import { DropCommandContext } from "./esql_parser"; +import { RenameVariableContext } from "./esql_parser"; +import { RenameCommandContext } from "./esql_parser"; +import { RenameClauseContext } from "./esql_parser"; +import { DissectCommandContext } from "./esql_parser"; +import { GrokCommandContext } from "./esql_parser"; +import { CommandOptionsContext } from "./esql_parser"; +import { CommandOptionContext } from "./esql_parser"; import { BooleanValueContext } from "./esql_parser"; import { NumberContext } from "./esql_parser"; +import { DecimalValueContext } from "./esql_parser"; +import { IntegerValueContext } from "./esql_parser"; import { StringContext } from "./esql_parser"; import { ComparisonOperatorContext } from "./esql_parser"; import { ExplainCommandContext } from "./esql_parser"; import { SubqueryExpressionContext } from "./esql_parser"; +import { ShowCommandContext } from "./esql_parser"; /** @@ -55,58 +74,6 @@ import { SubqueryExpressionContext } from "./esql_parser"; * `esql_parser`. */ export interface esql_parserListener extends ParseTreeListener { - /** - * Enter a parse tree produced by the `nullLiteral` - * labeled alternative in `esql_parser.constant`. - * @param ctx the parse tree - */ - enterNullLiteral?: (ctx: NullLiteralContext) => void; - /** - * Exit a parse tree produced by the `nullLiteral` - * labeled alternative in `esql_parser.constant`. - * @param ctx the parse tree - */ - exitNullLiteral?: (ctx: NullLiteralContext) => void; - - /** - * Enter a parse tree produced by the `numericLiteral` - * labeled alternative in `esql_parser.constant`. - * @param ctx the parse tree - */ - enterNumericLiteral?: (ctx: NumericLiteralContext) => void; - /** - * Exit a parse tree produced by the `numericLiteral` - * labeled alternative in `esql_parser.constant`. - * @param ctx the parse tree - */ - exitNumericLiteral?: (ctx: NumericLiteralContext) => void; - - /** - * Enter a parse tree produced by the `booleanLiteral` - * labeled alternative in `esql_parser.constant`. - * @param ctx the parse tree - */ - enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; - /** - * Exit a parse tree produced by the `booleanLiteral` - * labeled alternative in `esql_parser.constant`. - * @param ctx the parse tree - */ - exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; - - /** - * Enter a parse tree produced by the `stringLiteral` - * labeled alternative in `esql_parser.constant`. - * @param ctx the parse tree - */ - enterStringLiteral?: (ctx: StringLiteralContext) => void; - /** - * Exit a parse tree produced by the `stringLiteral` - * labeled alternative in `esql_parser.constant`. - * @param ctx the parse tree - */ - exitStringLiteral?: (ctx: StringLiteralContext) => void; - /** * Enter a parse tree produced by the `decimalLiteral` * labeled alternative in `esql_parser.number`. @@ -203,6 +170,39 @@ export interface esql_parserListener extends ParseTreeListener { */ exitProcessingCommand?: (ctx: ProcessingCommandContext) => void; + /** + * Enter a parse tree produced by `esql_parser.enrichCommand`. + * @param ctx the parse tree + */ + enterEnrichCommand?: (ctx: EnrichCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.enrichCommand`. + * @param ctx the parse tree + */ + exitEnrichCommand?: (ctx: EnrichCommandContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.enrichWithClause`. + * @param ctx the parse tree + */ + enterEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; + /** + * Exit a parse tree produced by `esql_parser.enrichWithClause`. + * @param ctx the parse tree + */ + exitEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.mvExpandCommand`. + * @param ctx the parse tree + */ + enterMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.mvExpandCommand`. + * @param ctx the parse tree + */ + exitMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + /** * Enter a parse tree produced by `esql_parser.whereCommand`. * @param ctx the parse tree @@ -214,6 +214,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitWhereCommand?: (ctx: WhereCommandContext) => void; + /** + * Enter a parse tree produced by `esql_parser.whereBooleanExpression`. + * @param ctx the parse tree + */ + enterWhereBooleanExpression?: (ctx: WhereBooleanExpressionContext) => void; + /** + * Exit a parse tree produced by `esql_parser.whereBooleanExpression`. + * @param ctx the parse tree + */ + exitWhereBooleanExpression?: (ctx: WhereBooleanExpressionContext) => void; + /** * Enter a parse tree produced by `esql_parser.booleanExpression`. * @param ctx the parse tree @@ -225,6 +236,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitBooleanExpression?: (ctx: BooleanExpressionContext) => void; + /** + * Enter a parse tree produced by `esql_parser.regexBooleanExpression`. + * @param ctx the parse tree + */ + enterRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; + /** + * Exit a parse tree produced by `esql_parser.regexBooleanExpression`. + * @param ctx the parse tree + */ + exitRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; + /** * Enter a parse tree produced by `esql_parser.valueExpression`. * @param ctx the parse tree @@ -258,6 +280,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitMathFn?: (ctx: MathFnContext) => void; + /** + * Enter a parse tree produced by `esql_parser.mathEvalFn`. + * @param ctx the parse tree + */ + enterMathEvalFn?: (ctx: MathEvalFnContext) => void; + /** + * Exit a parse tree produced by `esql_parser.mathEvalFn`. + * @param ctx the parse tree + */ + exitMathEvalFn?: (ctx: MathEvalFnContext) => void; + /** * Enter a parse tree produced by `esql_parser.operatorExpression`. * @param ctx the parse tree @@ -313,6 +346,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitField?: (ctx: FieldContext) => void; + /** + * Enter a parse tree produced by `esql_parser.enrichFieldIdentifier`. + * @param ctx the parse tree + */ + enterEnrichFieldIdentifier?: (ctx: EnrichFieldIdentifierContext) => void; + /** + * Exit a parse tree produced by `esql_parser.enrichFieldIdentifier`. + * @param ctx the parse tree + */ + exitEnrichFieldIdentifier?: (ctx: EnrichFieldIdentifierContext) => void; + /** * Enter a parse tree produced by `esql_parser.userVariable`. * @param ctx the parse tree @@ -335,6 +379,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitFromCommand?: (ctx: FromCommandContext) => void; + /** + * Enter a parse tree produced by `esql_parser.metadata`. + * @param ctx the parse tree + */ + enterMetadata?: (ctx: MetadataContext) => void; + /** + * Exit a parse tree produced by `esql_parser.metadata`. + * @param ctx the parse tree + */ + exitMetadata?: (ctx: MetadataContext) => void; + /** * Enter a parse tree produced by `esql_parser.evalCommand`. * @param ctx the parse tree @@ -368,6 +423,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitSourceIdentifier?: (ctx: SourceIdentifierContext) => void; + /** + * Enter a parse tree produced by `esql_parser.enrichIdentifier`. + * @param ctx the parse tree + */ + enterEnrichIdentifier?: (ctx: EnrichIdentifierContext) => void; + /** + * Exit a parse tree produced by `esql_parser.enrichIdentifier`. + * @param ctx the parse tree + */ + exitEnrichIdentifier?: (ctx: EnrichIdentifierContext) => void; + /** * Enter a parse tree produced by `esql_parser.functionExpressionArgument`. * @param ctx the parse tree @@ -379,6 +445,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitFunctionExpressionArgument?: (ctx: FunctionExpressionArgumentContext) => void; + /** + * Enter a parse tree produced by `esql_parser.mathFunctionExpressionArgument`. + * @param ctx the parse tree + */ + enterMathFunctionExpressionArgument?: (ctx: MathFunctionExpressionArgumentContext) => void; + /** + * Exit a parse tree produced by `esql_parser.mathFunctionExpressionArgument`. + * @param ctx the parse tree + */ + exitMathFunctionExpressionArgument?: (ctx: MathFunctionExpressionArgumentContext) => void; + /** * Enter a parse tree produced by `esql_parser.qualifiedName`. * @param ctx the parse tree @@ -412,6 +489,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitIdentifier?: (ctx: IdentifierContext) => void; + /** + * Enter a parse tree produced by `esql_parser.mathFunctionIdentifier`. + * @param ctx the parse tree + */ + enterMathFunctionIdentifier?: (ctx: MathFunctionIdentifierContext) => void; + /** + * Exit a parse tree produced by `esql_parser.mathFunctionIdentifier`. + * @param ctx the parse tree + */ + exitMathFunctionIdentifier?: (ctx: MathFunctionIdentifierContext) => void; + /** * Enter a parse tree produced by `esql_parser.functionIdentifier`. * @param ctx the parse tree @@ -434,6 +522,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitConstant?: (ctx: ConstantContext) => void; + /** + * Enter a parse tree produced by `esql_parser.numericValue`. + * @param ctx the parse tree + */ + enterNumericValue?: (ctx: NumericValueContext) => void; + /** + * Exit a parse tree produced by `esql_parser.numericValue`. + * @param ctx the parse tree + */ + exitNumericValue?: (ctx: NumericValueContext) => void; + /** * Enter a parse tree produced by `esql_parser.limitCommand`. * @param ctx the parse tree @@ -479,15 +578,103 @@ export interface esql_parserListener extends ParseTreeListener { exitProjectCommand?: (ctx: ProjectCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.projectClause`. + * Enter a parse tree produced by `esql_parser.keepCommand`. + * @param ctx the parse tree + */ + enterKeepCommand?: (ctx: KeepCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.keepCommand`. + * @param ctx the parse tree + */ + exitKeepCommand?: (ctx: KeepCommandContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.dropCommand`. + * @param ctx the parse tree + */ + enterDropCommand?: (ctx: DropCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.dropCommand`. + * @param ctx the parse tree + */ + exitDropCommand?: (ctx: DropCommandContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.renameVariable`. + * @param ctx the parse tree + */ + enterRenameVariable?: (ctx: RenameVariableContext) => void; + /** + * Exit a parse tree produced by `esql_parser.renameVariable`. + * @param ctx the parse tree + */ + exitRenameVariable?: (ctx: RenameVariableContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.renameCommand`. + * @param ctx the parse tree + */ + enterRenameCommand?: (ctx: RenameCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.renameCommand`. + * @param ctx the parse tree + */ + exitRenameCommand?: (ctx: RenameCommandContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.renameClause`. + * @param ctx the parse tree + */ + enterRenameClause?: (ctx: RenameClauseContext) => void; + /** + * Exit a parse tree produced by `esql_parser.renameClause`. + * @param ctx the parse tree + */ + exitRenameClause?: (ctx: RenameClauseContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.dissectCommand`. + * @param ctx the parse tree + */ + enterDissectCommand?: (ctx: DissectCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.dissectCommand`. + * @param ctx the parse tree + */ + exitDissectCommand?: (ctx: DissectCommandContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.grokCommand`. * @param ctx the parse tree */ - enterProjectClause?: (ctx: ProjectClauseContext) => void; + enterGrokCommand?: (ctx: GrokCommandContext) => void; /** - * Exit a parse tree produced by `esql_parser.projectClause`. + * Exit a parse tree produced by `esql_parser.grokCommand`. * @param ctx the parse tree */ - exitProjectClause?: (ctx: ProjectClauseContext) => void; + exitGrokCommand?: (ctx: GrokCommandContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.commandOptions`. + * @param ctx the parse tree + */ + enterCommandOptions?: (ctx: CommandOptionsContext) => void; + /** + * Exit a parse tree produced by `esql_parser.commandOptions`. + * @param ctx the parse tree + */ + exitCommandOptions?: (ctx: CommandOptionsContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.commandOption`. + * @param ctx the parse tree + */ + enterCommandOption?: (ctx: CommandOptionContext) => void; + /** + * Exit a parse tree produced by `esql_parser.commandOption`. + * @param ctx the parse tree + */ + exitCommandOption?: (ctx: CommandOptionContext) => void; /** * Enter a parse tree produced by `esql_parser.booleanValue`. @@ -511,6 +698,28 @@ export interface esql_parserListener extends ParseTreeListener { */ exitNumber?: (ctx: NumberContext) => void; + /** + * Enter a parse tree produced by `esql_parser.decimalValue`. + * @param ctx the parse tree + */ + enterDecimalValue?: (ctx: DecimalValueContext) => void; + /** + * Exit a parse tree produced by `esql_parser.decimalValue`. + * @param ctx the parse tree + */ + exitDecimalValue?: (ctx: DecimalValueContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.integerValue`. + * @param ctx the parse tree + */ + enterIntegerValue?: (ctx: IntegerValueContext) => void; + /** + * Exit a parse tree produced by `esql_parser.integerValue`. + * @param ctx the parse tree + */ + exitIntegerValue?: (ctx: IntegerValueContext) => void; + /** * Enter a parse tree produced by `esql_parser.string`. * @param ctx the parse tree @@ -554,5 +763,16 @@ export interface esql_parserListener extends ParseTreeListener { * @param ctx the parse tree */ exitSubqueryExpression?: (ctx: SubqueryExpressionContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.showCommand`. + * @param ctx the parse tree + */ + enterShowCommand?: (ctx: ShowCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.showCommand`. + * @param ctx the parse tree + */ + exitShowCommand?: (ctx: ShowCommandContext) => void; } diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts index ec8cfe8e596c1..92b2e8f7c31d1 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts @@ -85,4 +85,32 @@ export const comparisonCommandsDefinitions: AutocompleteCommandDefinition[] = [ }), sortText: 'D', }, + { + label: 'like', + insertText: 'like', + kind: 11, + detail: i18n.translate('monaco.esql.autocomplete.likeDoc', { + defaultMessage: 'Filter data based on string patterns', + }), + sortText: 'D', + }, + { + label: 'rlike', + insertText: 'rlike', + kind: 11, + detail: i18n.translate('monaco.esql.autocomplete.rlikeDoc', { + defaultMessage: 'Filter data based on string regular expressions', + }), + sortText: 'D', + }, + { + label: 'in', + insertText: 'in', + kind: 11, + detail: i18n.translate('monaco.esql.autocomplete.inDoc', { + defaultMessage: + 'Tests if the value an expression takes is contained in a list of other expressions', + }), + sortText: 'D', + }, ]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts index aa9a9f1777ff3..4a5a147ffcbde 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts @@ -9,6 +9,23 @@ import { i18n } from '@kbn/i18n'; import type { AutocompleteCommandDefinition } from '../types'; +export const buildPoliciesDefinitions = ( + policies: Array<{ name: string; indices: string[] }> +): AutocompleteCommandDefinition[] => + policies.map(({ name: label, indices }) => ({ + label, + insertText: label, + kind: 5, + detail: i18n.translate('monaco.esql.autocomplete.policyDefinition', { + defaultMessage: `Policy defined on {count, plural, one {index} other {indices}}: {indices}`, + values: { + count: indices.length, + indices: indices.join(', '), + }, + }), + sortText: 'D', + })); + export const buildFieldsDefinitions = (fields: string[]): AutocompleteCommandDefinition[] => fields.map((label) => ({ label, @@ -20,6 +37,37 @@ export const buildFieldsDefinitions = (fields: string[]): AutocompleteCommandDef sortText: 'D', })); +export const buildNoPoliciesAvailableDefinition = (): AutocompleteCommandDefinition[] => [ + { + label: i18n.translate('monaco.esql.autocomplete.noPoliciesLabel', { + defaultMessage: 'No available policy', + }), + insertText: '', + kind: 26, + detail: i18n.translate('monaco.esql.autocomplete.noPoliciesLabelsFound', { + defaultMessage: 'No policies found', + }), + sortText: 'D', + }, +]; + +export const buildMatchingFieldsDefinition = ( + matchingField: string, + fields: string[] +): AutocompleteCommandDefinition[] => + fields.map((label) => ({ + label, + insertText: label, + kind: 4, + detail: i18n.translate('monaco.esql.autocomplete.matchingFieldDefinition', { + defaultMessage: `Use to match on {matchingField} on the policy`, + values: { + matchingField, + }, + }), + sortText: 'D', + })); + export const buildNewVarDefinition = (label: string): AutocompleteCommandDefinition => { return { label, diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts index 119a443c40190..53add21af9f1a 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts @@ -11,21 +11,408 @@ import { buildDocumentation } from './utils'; import type { AutocompleteCommandDefinition } from '../types'; -export const roundCommandDefinition: AutocompleteCommandDefinition = { - label: 'round', - insertText: 'round', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.roundDoc', { - defaultMessage: - 'Returns a number rounded to the decimal, specified by he closest integer value. The default is to round to an integer.', - }), - documentation: { - value: buildDocumentation('round(grouped[T]): aggregated[T]', [ - 'from index where field="value" | eval rounded = round(field)', - ]), - }, - sortText: 'C', -}; +export const whereCommandDefinition: AutocompleteCommandDefinition[] = [ + { + label: 'cidr_match', + insertText: 'cidr_match', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.cidrMatchDoc', { + defaultMessage: + 'The function takes a first parameter of type IP, followed by one or more parameters evaluated to a CIDR specificatione.', + }), + documentation: { + value: buildDocumentation('cidr_match(grouped[T]): aggregated[T]', [ + 'from index | eval cidr="10.0.0.0/8" | where cidr_match(ip_field, "127.0.0.1/30", cidr)', + ]), + }, + sortText: 'C', + }, +]; + +export const mathCommandDefinition: AutocompleteCommandDefinition[] = [ + { + label: 'round', + insertText: 'round', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.roundDoc', { + defaultMessage: + 'Returns a number rounded to the decimal, specified by he closest integer value. The default is to round to an integer.', + }), + documentation: { + value: buildDocumentation('round(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval rounded = round(field)', + ]), + }, + sortText: 'C', + }, + { + label: 'abs', + insertText: 'abs', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.absDoc', { + defaultMessage: 'Returns the absolute value.', + }), + documentation: { + value: buildDocumentation('abs(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval abs_value = abs(field)', + ]), + }, + sortText: 'C', + }, + { + label: 'pow', + insertText: 'pow', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.powDoc', { + defaultMessage: + 'Returns the the value of a base (first argument) raised to a power (second argument).', + }), + documentation: { + value: buildDocumentation('pow(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval s = POW(field, exponent)', + ]), + }, + sortText: 'C', + }, + { + label: 'log10', + insertText: 'log10', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.log10Doc', { + defaultMessage: 'Returns the log base 10.', + }), + documentation: { + value: buildDocumentation('log10(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval s = log10(field)', + ]), + }, + sortText: 'C', + }, + { + label: 'concat', + insertText: 'concat', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.concatDoc', { + defaultMessage: 'Concatenates two or more strings.', + }), + documentation: { + value: buildDocumentation('concat(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval concatenated = concat(field1, "-", field2)', + ]), + }, + sortText: 'C', + }, + { + label: 'substring', + insertText: 'substring', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.substringDoc', { + defaultMessage: + 'Returns a substring of a string, specified by a start position and an optional length. This example returns the first three characters of every last name.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval new_string = substring(field, 1, 3)', + ]), + }, + sortText: 'C', + }, + { + label: 'trim', + insertText: 'trim', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.trimDoc', { + defaultMessage: 'Removes leading and trailing whitespaces from strings.', + }), + documentation: { + value: buildDocumentation('trim(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval new_string = trim(field)', + ]), + }, + sortText: 'C', + }, + { + label: 'starts_with', + insertText: 'starts_with', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.startsWithDoc', { + defaultMessage: + 'Returns a boolean that indicates whether a keyword string starts with another string.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval new_string = starts_with(field, "a")', + ]), + }, + sortText: 'C', + }, + { + label: 'split', + insertText: 'split', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.splitDoc', { + defaultMessage: 'Splits a single valued string into multiple strings.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `ROW words="foo;bar;baz;qux;quux;corge" + | EVAL word = SPLIT(words, ";")`, + ]), + }, + sortText: 'C', + }, + { + label: 'to_string', + insertText: 'to_string', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.toStringDoc', { + defaultMessage: 'Converts to string.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value"" + | EVAL string = to_string(field)`, + ]), + }, + sortText: 'C', + }, + { + label: 'to_boolean', + insertText: 'to_boolean', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.toBooleanDoc', { + defaultMessage: 'Converts to boolean.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value"" + | EVAL bool = to_boolean(field)`, + ]), + }, + sortText: 'C', + }, + { + label: 'to_datetime', + insertText: 'to_datetime', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.toDateTimeDoc', { + defaultMessage: 'Converts to date.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value"" + | EVAL datetime = to_datetime(field)`, + ]), + }, + sortText: 'C', + }, + { + label: 'to_double', + insertText: 'to_double', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.toDoubleDoc', { + defaultMessage: 'Converts to double.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value"" + | EVAL double = to_double(field)`, + ]), + }, + sortText: 'C', + }, + { + label: 'to_integer', + insertText: 'to_integer', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.toIntegerDoc', { + defaultMessage: 'Converts to integer.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value"" + | EVAL int = to_integer(field)`, + ]), + }, + sortText: 'C', + }, + { + label: 'to_long', + insertText: 'to_long', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.toLongDoc', { + defaultMessage: 'Converts to long.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value"" + | EVAL long = to_long(field)`, + ]), + }, + sortText: 'C', + }, + { + label: 'to_unsigned_long', + insertText: 'to_unsigned_long', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.toUnsignedLongDoc', { + defaultMessage: 'Converts to unsigned long.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value"" + | EVAL long = to_unsigned_long(field)`, + ]), + }, + sortText: 'C', + }, + { + label: 'to_ip', + insertText: 'to_ip', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.toIpDoc', { + defaultMessage: 'Converts to ip.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value"" + | EVAL ip = to_ip(field)`, + ]), + }, + sortText: 'C', + }, + { + label: 'to_version', + insertText: 'to_version', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.toVersionDoc', { + defaultMessage: 'Converts to version.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value"" + | EVAL version = to_version(field)`, + ]), + }, + sortText: 'C', + }, + { + label: 'date_format', + insertText: 'date_format', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.dateFormatDoc', { + defaultMessage: `Returns a string representation of a date in the provided format. If no format is specified, the "yyyy-MM-dd'T'HH:mm:ss.SSSZ" format is used.`, + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval hired = date_format(hire_date, "YYYY-MM-dd")', + ]), + }, + sortText: 'C', + }, + { + label: 'date_trunc', + insertText: 'date_trunc', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.dateTruncDoc', { + defaultMessage: `Rounds down a date to the closest interval.`, + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval year_hired = DATE_TRUNC(hire_date, 1 year)', + ]), + }, + sortText: 'C', + }, + { + label: 'date_parse', + insertText: 'date_parse', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.dateParseDoc', { + defaultMessage: `Parse dates from strings.`, + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value" | eval year_hired = date_parse(hire_date, yyyy-MM-dd'T'HH:mm:ss.SSS'Z')`, + ]), + }, + sortText: 'C', + }, + { + label: 'auto_bucket', + insertText: 'auto_bucket', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.autoBucketDoc', { + defaultMessage: `Automatically bucket dates based on a given range and bucket target.`, + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval hd = auto_bucket(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")', + ]), + }, + sortText: 'C', + }, + { + label: 'is_finite', + insertText: 'is_finite', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.isFiniteDoc', { + defaultMessage: 'Returns a boolean that indicates whether its input is a finite number.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval s = is_finite(field/0)', + ]), + }, + sortText: 'C', + }, + { + label: 'is_infinite', + insertText: 'is_infinite', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.isInfiniteDoc', { + defaultMessage: 'Returns a boolean that indicates whether its input is infinite.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + 'from index where field="value" | eval s = is_infinite(field/0)', + ]), + }, + sortText: 'C', + }, + { + label: 'case', + insertText: 'case', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.caseDoc', { + defaultMessage: + 'Accepts pairs of conditions and values. The function returns the value that belongs to the first condition that evaluates to `true`. If the number of arguments is odd, the last argument is the default value which is returned when no condition matches.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value" | eval type = case( + languages <= 1, "monolingual", + languages <= 2, "bilingual", + "polyglot")`, + ]), + }, + sortText: 'C', + }, + { + label: 'length', + insertText: 'length', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.lengthDoc', { + defaultMessage: 'Returns the character length of a string.', + }), + documentation: { + value: buildDocumentation('substring(grouped[T]): aggregated[T]', [ + `from index where field="value" | eval fn_length = length(field)`, + ]), + }, + sortText: 'C', + }, +]; export const aggregationFunctionsDefinitions: AutocompleteCommandDefinition[] = [ { @@ -84,4 +471,75 @@ export const aggregationFunctionsDefinitions: AutocompleteCommandDefinition[] = }, sortText: 'C', }, + { + label: 'count', + insertText: 'count', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.countDoc', { + defaultMessage: 'Returns the count of the values in a field.', + }), + documentation: { + value: buildDocumentation('count(grouped[T]): aggregated[T]', [ + 'from index | stats count = count(field)', + ]), + }, + sortText: 'C', + }, + { + label: 'count_distinct', + insertText: 'count_distinct', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.countDistinctDoc', { + defaultMessage: 'Returns the count of distinct values in a field.', + }), + documentation: { + value: buildDocumentation('count(grouped[T]): aggregated[T]', [ + 'from index | stats count = count_distinct(field)', + ]), + }, + sortText: 'C', + }, + { + label: 'median', + insertText: 'median', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.medianDoc', { + defaultMessage: 'Returns the 50% percentile.', + }), + documentation: { + value: buildDocumentation('count(grouped[T]): aggregated[T]', [ + 'from index | stats count = median(field)', + ]), + }, + sortText: 'C', + }, + { + label: 'median_absolute_deviation', + insertText: 'median_absolute_deviation', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.medianDeviationDoc', { + defaultMessage: + 'Returns the median of each data point’s deviation from the median of the entire sample.', + }), + documentation: { + value: buildDocumentation('count(grouped[T]): aggregated[T]', [ + 'from index | stats count = median_absolute_deviation(field)', + ]), + }, + sortText: 'C', + }, + { + label: 'percentile', + insertText: 'percentile', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.percentiletDoc', { + defaultMessage: 'Returns the n percentile of a field.', + }), + documentation: { + value: buildDocumentation('percentile(grouped[T]): aggregated[T]', [ + 'from index | stats pct = percentile(field, 90)', + ]), + }, + sortText: 'C', + }, ]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts index ef096d678acc3..e1fb514cfa4de 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts @@ -6,7 +6,11 @@ * Side Public License, v 1. */ -export { aggregationFunctionsDefinitions, roundCommandDefinition } from './functions_commands'; +export { + aggregationFunctionsDefinitions, + mathCommandDefinition, + whereCommandDefinition, +} from './functions_commands'; export { sourceCommandsDefinitions } from './source_commands'; export { processingCommandsDefinitions, pipeDefinition } from './processing_commands'; @@ -17,6 +21,7 @@ export { export { mathOperatorsCommandsDefinitions, assignOperatorDefinition, + asOperatorDefinition, byOperatorDefinition, openBracketDefinition, closeBracketDefinition, diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts index 21a5f6260cedd..91ccb74cb9501 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts @@ -11,7 +11,7 @@ import type { AutocompleteCommandDefinition } from '../types'; export const byOperatorDefinition: AutocompleteCommandDefinition = { label: 'by', - insertText: 'by ', + insertText: 'by', kind: 21, detail: i18n.translate('monaco.esql.autocomplete.byDoc', { defaultMessage: 'By', @@ -19,6 +19,36 @@ export const byOperatorDefinition: AutocompleteCommandDefinition = { sortText: 'D', }; +export const onOperatorDefinition: AutocompleteCommandDefinition = { + label: 'on', + insertText: 'on', + kind: 21, + detail: i18n.translate('monaco.esql.autocomplete.onDoc', { + defaultMessage: 'On', + }), + sortText: 'D', +}; + +export const withOperatorDefinition: AutocompleteCommandDefinition = { + label: 'with', + insertText: 'with', + kind: 21, + detail: i18n.translate('monaco.esql.autocomplete.withDoc', { + defaultMessage: 'With', + }), + sortText: 'D', +}; + +export const asOperatorDefinition: AutocompleteCommandDefinition = { + label: 'as', + insertText: 'as', + kind: 11, + detail: i18n.translate('monaco.esql.autocomplete.asDoc', { + defaultMessage: 'As', + }), + sortText: 'D', +}; + export const assignOperatorDefinition: AutocompleteCommandDefinition = { label: '=', insertText: '=', diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts index 8dbc1ebe3d9c0..a53330d638158 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts @@ -66,6 +66,46 @@ export const processingCommandsDefinitions: AutocompleteCommandDefinition[] = [ }, sortText: 'B', }, + { + label: 'keep', + insertText: 'keep', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.keepDoc', { + defaultMessage: 'Rearranges fields in the input table by applying the keep clauses in fields', + }), + documentation: { + value: buildDocumentation('keep fieldSpecification `,` fieldSpecification *', [ + '… | keep a,b', + ]), + }, + sortText: 'B', + }, + { + label: 'rename', + insertText: 'rename', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.renameDoc', { + defaultMessage: 'Renames an old column to a new one', + }), + documentation: { + value: buildDocumentation('rename new as old', ['… | rename a as b']), + }, + sortText: 'B', + }, + { + label: 'drop', + insertText: 'drop', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.dropDoc', { + defaultMessage: 'Drops columns', + }), + documentation: { + value: buildDocumentation('drop fieldSpecification `,` fieldSpecification *', [ + '… | drop a,b', + ]), + }, + sortText: 'B', + }, { label: 'sort', insertText: 'sort', @@ -96,4 +136,61 @@ export const processingCommandsDefinitions: AutocompleteCommandDefinition[] = [ }, sortText: 'B', }, + { + label: 'dissect', + insertText: 'dissect', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.dissectDoc', { + defaultMessage: + 'Extracts multiple string values from a single string input, based on a pattern', + }), + documentation: { + value: buildDocumentation( + 'dissect (append_separator=)?', + ['… | dissect a "%{b} %{c}";'] + ), + }, + sortText: 'B', + }, + { + label: 'grok', + insertText: 'grok', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.grokDoc', { + defaultMessage: + 'Extracts multiple string values from a single string input, based on a pattern', + }), + documentation: { + value: buildDocumentation('grok ', [ + '… | grok a "%{b} %{c}";', + ]), + }, + sortText: 'B', + }, + { + label: 'mv_expand', + insertText: 'mv_expand', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.mvExpandDoc', { + defaultMessage: 'Expands multivalued fields into one row per value, duplicating other fields', + }), + documentation: { + value: buildDocumentation('mv_expand field', [ + 'ROW a=[1,2,3], b="b", j=["a","b"] | MV_EXPAND a', + ]), + }, + sortText: 'B', + }, + { + label: 'enrich', + insertText: 'enrich', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.enrichDoc', { + defaultMessage: 'Enrich table with another table', + }), + documentation: { + value: buildDocumentation('enrich policy', ['... | ENRICH a']), + }, + sortText: 'B', + }, ]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts index 157d111154f1f..bbcdb04060689 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts @@ -38,12 +38,22 @@ describe('autocomplete_listener', () => { testSuggestions('f', ['from']); testSuggestions('from ', ['SourceIdentifier']); testSuggestions('from a,', ['SourceIdentifier']); - testSuggestions('from a, b ', ['|']); + testSuggestions('from a, b ', ['SourceIdentifier']); }); describe('where', () => { - testSuggestions('from a | where ', ['FieldIdentifier']); - testSuggestions('from a | where "field" ', ['==', '!=', '<', '>', '<=', '>=']); + testSuggestions('from a | where ', ['cidr_match', 'FieldIdentifier']); + testSuggestions('from a | where "field" ', [ + '==', + '!=', + '<', + '>', + '<=', + '>=', + 'like', + 'rlike', + 'in', + ]); testSuggestions('from a | where "field" >= ', ['FieldIdentifier']); testSuggestions('from a | where "field" >= "field1" ', ['or', 'and', '|']); testSuggestions('from a | where "field" >= "field1" and ', ['FieldIdentifier']); @@ -54,9 +64,32 @@ describe('autocomplete_listener', () => { '>', '<=', '>=', + 'like', + 'rlike', + 'in', + ]); + testSuggestions('from a | stats a=avg("field") | where a ', [ + '==', + '!=', + '<', + '>', + '<=', + '>=', + 'like', + 'rlike', + 'in', + ]); + testSuggestions('from a | stats a=avg("b") | where "c" ', [ + '==', + '!=', + '<', + '>', + '<=', + '>=', + 'like', + 'rlike', + 'in', ]); - testSuggestions('from a | stats a=avg("field") | where a ', ['==', '!=', '<', '>', '<=', '>=']); - testSuggestions('from a | stats a=avg("b") | where "c" ', ['==', '!=', '<', '>', '<=', '>=']); testSuggestions('from a | where "field" >= "field1" and "field2 == ', ['FieldIdentifier']); }); @@ -72,11 +105,25 @@ describe('autocomplete_listener', () => { testSuggestions('from a | limit 4 ', ['|']); }); + describe('mv_expand', () => { + testSuggestions('from a | mv_expand ', ['FieldIdentifier']); + testSuggestions('from a | mv_expand a ', ['|']); + }); + describe('stats', () => { testSuggestions('from a | stats ', ['var0']); testSuggestions('from a | stats a ', ['=']); - testSuggestions('from a | stats a=', ['avg', 'max', 'min', 'sum', 'FieldIdentifier']); - testSuggestions('from a | stats a=b', ['|', 'by']); + testSuggestions('from a | stats a=', [ + 'avg', + 'max', + 'min', + 'sum', + 'count', + 'count_distinct', + 'median', + 'median_absolute_deviation', + 'percentile', + ]); testSuggestions('from a | stats a=b by ', ['FieldIdentifier']); testSuggestions('from a | stats a=c by d', ['|']); testSuggestions('from a | stats a=b, ', ['var0']); @@ -90,11 +137,75 @@ describe('autocomplete_listener', () => { testSuggestions('from a | stats a=min(b), b=max(', ['FieldIdentifier']); }); + describe('enrich', () => { + for (const prevCommand of [ + '', + '| enrich other-policy ', + '| enrich other-policy on b ', + '| enrich other-policy with c ', + ]) { + testSuggestions(`from a ${prevCommand}| enrich`, ['PolicyIdentifier']); + testSuggestions(`from a ${prevCommand}| enrich policy `, ['|', 'on', 'with']); + testSuggestions(`from a ${prevCommand}| enrich policy on `, [ + 'PolicyMatchingFieldIdentifier', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b `, ['|', 'with']); + testSuggestions(`from a ${prevCommand}| enrich policy on b with `, [ + 'var0', + 'PolicyFieldIdentifier', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 `, ['=', '|']); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = `, [ + 'PolicyFieldIdentifier', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c `, ['|']); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c, `, [ + 'var1', + 'PolicyFieldIdentifier', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c, var1 `, ['=', '|']); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c, var1 = `, [ + 'PolicyFieldIdentifier', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy with `, [ + 'var0', + 'PolicyFieldIdentifier', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy with c`, ['=', '|']); + } + }); + describe('eval', () => { testSuggestions('from a | eval ', ['var0']); testSuggestions('from a | eval a ', ['=']); - testSuggestions('from a | eval a=', ['round', 'FieldIdentifier']); - testSuggestions('from a | eval a=b', ['|', '+', '-', '/', '*']); + testSuggestions('from a | eval a=', [ + 'round', + 'abs', + 'pow', + 'log10', + 'concat', + 'substring', + 'trim', + 'starts_with', + 'split', + 'to_string', + 'to_boolean', + 'to_datetime', + 'to_double', + 'to_integer', + 'to_long', + 'to_unsigned_long', + 'to_ip', + 'to_version', + 'date_format', + 'date_trunc', + 'date_parse', + 'auto_bucket', + 'is_finite', + 'is_infinite', + 'case', + 'length', + ]); testSuggestions('from a | eval a=b, ', ['var0']); testSuggestions('from a | eval a=round', ['(']); testSuggestions('from a | eval a=round(', ['FieldIdentifier']); diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts index d3cda17124349..ad439caad1dce 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts @@ -10,7 +10,12 @@ import type { AutocompleteCommandDefinition, UserDefinedVariables } from './type import { DynamicAutocompleteItem } from './dymanic_item'; import { esql_parserListener as ESQLParserListener } from '../../antlr/esql_parser_listener'; -import { esql_parser, esql_parser as ESQLParser } from '../../antlr/esql_parser'; +import { + esql_parser, + esql_parser as ESQLParser, + EnrichCommandContext, + EnrichWithClauseContext, +} from '../../antlr/esql_parser'; import { processingCommandsDefinitions, @@ -26,10 +31,12 @@ import { closeBracketDefinition, mathOperatorsCommandsDefinitions, aggregationFunctionsDefinitions, - roundCommandDefinition, + mathCommandDefinition, + whereCommandDefinition, assignOperatorDefinition, buildConstantsDefinitions, buildNewVarDefinition, + asOperatorDefinition, } from './autocomplete_definitions'; import { @@ -45,22 +52,49 @@ import { SourceIdentifierContext, UserVariableContext, BooleanExpressionContext, + RegexBooleanExpressionContext, + WhereBooleanExpressionContext, LimitCommandContext, ValueExpressionContext, + KeepCommandContext, + DropCommandContext, + RenameCommandContext, + DissectCommandContext, + GrokCommandContext, + MvExpandCommandContext, } from '../../antlr/esql_parser'; +import { + onOperatorDefinition, + withOperatorDefinition, +} from './autocomplete_definitions/operators_commands'; + +export function nonNullable(v: T): v is NonNullable { + return v != null; +} export class AutocompleteListener implements ESQLParserListener { private suggestions: Array = []; private readonly userDefinedVariables: UserDefinedVariables = { sourceIdentifiers: [], + policyIdentifiers: [], }; private readonly tables: string[][] = []; private parentContext: number | undefined; - private get fields() { - return this.tables.length > 1 - ? buildConstantsDefinitions(this.tables.at(-2)!) - : [DynamicAutocompleteItem.FieldIdentifier]; + private get fields(): [DynamicAutocompleteItem] { + return [DynamicAutocompleteItem.FieldIdentifier]; + } + + private get policies(): [DynamicAutocompleteItem] { + return [DynamicAutocompleteItem.PolicyIdentifier]; + } + + private get policyFields(): [DynamicAutocompleteItem] { + return [DynamicAutocompleteItem.PolicyFieldIdentifier]; + } + + private get policyMatchingField(): [DynamicAutocompleteItem] { + return [DynamicAutocompleteItem.PolicyMatchingFieldIdentifier]; } private get hasSuggestions() { @@ -71,16 +105,23 @@ export class AutocompleteListener implements ESQLParserListener { return node && node.payload?.startIndex >= 0; } - private getEndCommandSuggestions(skipDefinitions: AutocompleteCommandDefinition[] = []) { - const suggestions = [pipeDefinition]; - - if ( - !skipDefinitions.find((i) => i === byOperatorDefinition) && - this.parentContext === ESQLParser.STATS - ) { - suggestions.push(byOperatorDefinition); + private applyConditionalSuggestion( + skipDefinitions: AutocompleteCommandDefinition[], + targetDefinition: AutocompleteCommandDefinition, + context: number + ) { + if (!skipDefinitions.find((i) => i === targetDefinition) && this.parentContext === context) { + return targetDefinition; } - return suggestions; + } + + private getEndCommandSuggestions(skipDefinitions: AutocompleteCommandDefinition[] = []) { + return [ + pipeDefinition, + this.applyConditionalSuggestion(skipDefinitions, byOperatorDefinition, ESQLParser.STATS), + this.applyConditionalSuggestion(skipDefinitions, onOperatorDefinition, ESQLParser.ENRICH), + this.applyConditionalSuggestion(skipDefinitions, withOperatorDefinition, ESQLParser.ENRICH), + ].filter(nonNullable); } private getNewVarName() { @@ -112,11 +153,13 @@ export class AutocompleteListener implements ESQLParserListener { exitSourceCommand(ctx: SourceCommandContext) { if (ctx.exception) { this.suggestions = sourceCommandsDefinitions; - } else if (!this.hasSuggestions) { - this.suggestions = this.getEndCommandSuggestions(); } } + enterSourceIdentifier(ctx: SourceIdentifierContext) { + this.suggestions = [DynamicAutocompleteItem.SourceIdentifier]; + } + exitSourceIdentifier(ctx: SourceIdentifierContext) { if (!ctx.childCount) { this.suggestions = [DynamicAutocompleteItem.SourceIdentifier]; @@ -141,6 +184,11 @@ export class AutocompleteListener implements ESQLParserListener { enterStatsCommand(ctx: StatsCommandContext) { this.suggestions = []; this.parentContext = ESQLParser.STATS; + const fn = ctx.fields(); + if (!fn) { + this.suggestions = [buildNewVarDefinition(this.getNewVarName())]; + return; + } } enterEvalCommand(ctx: EvalCommandContext) { @@ -155,7 +203,84 @@ export class AutocompleteListener implements ESQLParserListener { } } + exitKeepCommand?(ctx: KeepCommandContext) { + const qn = ctx.qualifiedNames(); + if (qn && qn.text) { + if (qn.text.slice(-1) !== ',') { + this.suggestions = this.getEndCommandSuggestions(); + } + } + } + + exitDropCommand?(ctx: DropCommandContext) { + const qn = ctx.qualifiedNames(); + if (qn && qn.text) { + if (qn.text.slice(-1) !== ',') { + this.suggestions = this.getEndCommandSuggestions(); + } + } + } + + enterRenameCommand(ctx: RenameCommandContext) { + this.parentContext = ESQLParser.RENAME; + } + + exitRenameCommand?(ctx: RenameCommandContext) { + const rc = ctx.renameClause(); + const commaExists = ctx.COMMA(); + if (!rc[0].exception) { + const qn = rc[0].renameVariable(); + const asExists = this.isTerminalNodeExists(rc[0].AS()); + if (asExists && qn && !qn.text) { + this.suggestions = []; + } + if (qn && qn.text) { + if (!commaExists.length) { + this.suggestions = this.getEndCommandSuggestions(); + } + } + } + } + + exitDissectCommand?(ctx: DissectCommandContext) { + const qn = ctx.qualifiedNames(); + const pattern = ctx.string(); + if (qn && qn.text && pattern && pattern.text && pattern.text !== '') { + this.suggestions = this.getEndCommandSuggestions(); + } + } + + exitGrokCommand?(ctx: GrokCommandContext) { + const qn = ctx.qualifiedNames(); + const pattern = ctx.string(); + if (qn && qn.text && pattern && pattern.text && pattern.text !== '') { + this.suggestions = this.getEndCommandSuggestions(); + } + } + + exitMvExpandCommand?(ctx: MvExpandCommandContext) { + const qn = ctx.qualifiedNames(); + if (qn && qn.text) { + this.suggestions = this.getEndCommandSuggestions(); + } + } + exitQualifiedName(ctx: QualifiedNameContext) { + const isInEval = this.parentContext === ESQLParser.EVAL; + const isInStats = this.parentContext === ESQLParser.STATS; + const isInRename = this.parentContext === ESQLParser.RENAME; + if (this.parentContext && isInRename) { + if (!ctx.exception && ctx.text) { + this.suggestions = [asOperatorDefinition]; + } + } + if (this.parentContext && (isInStats || isInEval)) { + this.suggestions = [ + ...this.getEndCommandSuggestions(), + ...(isInEval ? mathOperatorsCommandsDefinitions : []), + ]; + } + if ( ctx .identifier() @@ -205,12 +330,12 @@ export class AutocompleteListener implements ESQLParserListener { const ve = ctx.valueExpression(); if (!ve) { if (this.parentContext === ESQLParser.STATS) { - this.suggestions = [...aggregationFunctionsDefinitions, ...this.fields]; + this.suggestions = [...aggregationFunctionsDefinitions]; return; } if (this.parentContext === ESQLParser.EVAL) { - this.suggestions = [roundCommandDefinition, ...this.fields]; + this.suggestions = [...mathCommandDefinition]; return; } } @@ -222,7 +347,9 @@ export class AutocompleteListener implements ESQLParserListener { const isInEval = this.parentContext === ESQLParser.EVAL; if (this.parentContext && (isInStats || isInEval)) { - const hasFN = ctx.tryGetToken(esql_parser.UNARY_FUNCTION, 0); + const hasFN = + ctx.tryGetToken(esql_parser.UNARY_FUNCTION, 0) || + ctx.tryGetToken(esql_parser.MATH_FUNCTION, 0); const hasLP = ctx.tryGetToken(esql_parser.LP, 0); const hasRP = ctx.tryGetToken(esql_parser.RP, 0); @@ -239,10 +366,12 @@ export class AutocompleteListener implements ESQLParserListener { } } else { if (ctx.childCount === 1) { - this.suggestions = [ - ...this.getEndCommandSuggestions(), - ...(isInEval ? mathOperatorsCommandsDefinitions : []), - ]; + if (ctx.text && ctx.text.indexOf('(') === -1) { + this.suggestions = [ + ...(isInEval ? mathCommandDefinition : []), + ...(isInStats ? aggregationFunctionsDefinitions : []), + ]; + } return; } } @@ -250,25 +379,117 @@ export class AutocompleteListener implements ESQLParserListener { } } + enterWhereBooleanExpression(ctx: WhereBooleanExpressionContext) { + this.suggestions = []; + } + enterWhereCommand(ctx: WhereCommandContext) { this.suggestions = []; this.parentContext = ESQLParser.WHERE; } + enterEnrichCommand(ctx: EnrichCommandContext) { + this.suggestions = []; + this.parentContext = ESQLParser.ENRICH; + } + + exitEnrichCommand(ctx: EnrichCommandContext) { + const policyName = ctx.enrichIdentifier().text; + if (policyName && !this.userDefinedVariables.policyIdentifiers.includes(policyName)) { + this.userDefinedVariables.policyIdentifiers.push(policyName); + } + + if (this.parentContext === ESQLParser.WITH) { + return; + } + if (!policyName) { + this.suggestions = this.policies; + } + + if (policyName) + if (this.parentContext === ESQLParser.ENRICH) { + const hasOn = this.isTerminalNodeExists(ctx.ON()); + if (hasOn && !ctx._matchField.text) { + this.suggestions = this.policyMatchingField; + } else { + this.suggestions = this.getEndCommandSuggestions( + hasOn ? [onOperatorDefinition] : undefined + ); + } + } + } + + enterEnrichWithClause(ctx: EnrichWithClauseContext) { + this.suggestions = []; + this.parentContext = ESQLParser.WITH; + } + + exitEnrichWithClause(ctx: EnrichWithClauseContext) { + const hasAssign = this.isTerminalNodeExists(ctx.ASSIGN()); + // Note: this gets filled only after the assign operation :( + if (ctx._newName?.text) { + this.tables.at(-1)?.push(ctx._newName.text); + } + + if (!ctx.exception && ctx.enrichFieldIdentifier().length === 1) { + // if it's after the assign operator, then suggest the fields from the policy + // TODO: need to check if the enrichFieldIdentifier given is a policyField or not and decide whether append the assignOperator + this.suggestions = !hasAssign + ? [assignOperatorDefinition, ...this.getEndCommandSuggestions()] + : this.policyFields; + } else { + this.suggestions = []; + if (!hasAssign) { + this.suggestions.push(buildNewVarDefinition(this.getNewVarName())); + } + if (!ctx._enrichField?.text) { + this.suggestions.push(...this.policyFields); + } + if (this.suggestions.length === 0) { + this.suggestions = this.getEndCommandSuggestions([ + onOperatorDefinition, + withOperatorDefinition, + ]); + } + } + } + exitWhereCommand(ctx: WhereCommandContext) { - const booleanExpression = ctx.booleanExpression(); + const booleanExpression = ctx.whereBooleanExpression(); if (booleanExpression.exception) { + if (!booleanExpression.text) { + this.suggestions = [...whereCommandDefinition, ...this.fields]; + return; + } this.suggestions = this.fields; return; } else { - const innerBooleanExpressions = booleanExpression.getRuleContexts(BooleanExpressionContext); + const innerBooleanExpressions = booleanExpression.getRuleContexts( + WhereBooleanExpressionContext + ); + const regexBooleanExpression = booleanExpression.getRuleContexts( + RegexBooleanExpressionContext + ); + + if (booleanExpression.WHERE_FUNCTIONS()) { + if (booleanExpression.COMMA().length) { + this.suggestions = []; + return; + } + } + + if (regexBooleanExpression.length) { + this.suggestions = []; + return; + } + if (innerBooleanExpressions.some((be) => be.exception)) { this.suggestions = this.fields; return; } } - if (!this.hasSuggestions) { + if (!this.hasSuggestions && !booleanExpression.WHERE_FUNCTIONS()) { this.suggestions = comparisonCommandsDefinitions; } } diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts index b819dc34059a1..621c8900447a0 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts @@ -9,10 +9,13 @@ export enum DynamicAutocompleteItem { SourceIdentifier = 'SourceIdentifier', FieldIdentifier = 'FieldIdentifier', + PolicyIdentifier = 'PolicyIdentifier', + PolicyFieldIdentifier = 'PolicyFieldIdentifier', + PolicyMatchingFieldIdentifier = 'PolicyMatchingFieldIdentifier', } +const DynamicAutocompleteItems = Object.values(DynamicAutocompleteItem); + export function isDynamicAutocompleteItem(v: unknown): v is DynamicAutocompleteItem { - return ( - v === DynamicAutocompleteItem.SourceIdentifier || v === DynamicAutocompleteItem.FieldIdentifier - ); + return DynamicAutocompleteItems.some((dai) => dai === v); } diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts index 58438baa298a9..0b64f0871b27a 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts +++ b/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts @@ -12,17 +12,21 @@ import { monaco } from '../../../..'; export interface ESQLCustomAutocompleteCallbacks { getSourceIdentifiers?: CallbackFn; getFieldsIdentifiers?: CallbackFn; + getPoliciesIdentifiers?: CallbackFn<{ name: string; indices: string[] }>; + getPolicyFieldsIdentifiers?: CallbackFn; + getPolicyMatchingFieldIdentifiers?: CallbackFn; } /** @internal **/ -type CallbackFn = (ctx: { +type CallbackFn = (ctx: { word: string; userDefinedVariables: UserDefinedVariables; -}) => string[] | Promise; +}) => T[] | Promise; /** @internal **/ export interface UserDefinedVariables { sourceIdentifiers: string[]; + policyIdentifiers: string[]; } /** @internal **/ diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts index 40393fe1b844d..4a407c3519769 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts @@ -11,7 +11,11 @@ import { DynamicAutocompleteItem, isDynamicAutocompleteItem } from '../autocompl import { buildFieldsDefinitions, buildSourcesDefinitions, + buildPoliciesDefinitions, + buildNoPoliciesAvailableDefinition, + buildMatchingFieldsDefinition, } from '../autocomplete/autocomplete_definitions/dynamic_commands'; +import { pipeDefinition } from '../autocomplete/autocomplete_definitions'; import type { AutocompleteCommandDefinition, @@ -20,11 +24,6 @@ import type { } from '../autocomplete/types'; import type { ESQLWorker } from '../../worker/esql_worker'; -const emptyCompletionList: monaco.languages.CompletionList = { - incomplete: false, - suggestions: [], -}; - export class ESQLCompletionAdapter implements monaco.languages.CompletionItemProvider { constructor( private worker: (...uris: monaco.Uri[]) => Promise, @@ -40,16 +39,20 @@ export class ESQLCompletionAdapter implements monaco.languages.CompletionItemPro userDefinedVariables: UserDefinedVariables; } ): Promise { - let result: AutocompleteCommandDefinition[] = []; - - for (const suggestion of suggestions) { - if (isDynamicAutocompleteItem(suggestion)) { + const allSuggestions: AutocompleteCommandDefinition[][] = await Promise.all( + suggestions.map(async (suggestion) => { + if (!isDynamicAutocompleteItem(suggestion)) { + return [suggestion]; + } let dynamicItems: AutocompleteCommandDefinition[] = []; if (suggestion === DynamicAutocompleteItem.SourceIdentifier) { dynamicItems = buildSourcesDefinitions( (await this.callbacks?.getSourceIdentifiers?.(ctx)) ?? [] ); + if (!ctx.word && ctx.userDefinedVariables.sourceIdentifiers.length) { + dynamicItems = [pipeDefinition]; + } } if (suggestion === DynamicAutocompleteItem.FieldIdentifier) { @@ -57,13 +60,34 @@ export class ESQLCompletionAdapter implements monaco.languages.CompletionItemPro (await this.callbacks?.getFieldsIdentifiers?.(ctx)) ?? [] ); } - result = [...result, ...dynamicItems]; - } else { - result = [...result, suggestion]; - } - } - return result; + if (suggestion === DynamicAutocompleteItem.PolicyIdentifier) { + const results = await this.callbacks?.getPoliciesIdentifiers?.(ctx); + dynamicItems = results?.length + ? buildPoliciesDefinitions(results) + : buildNoPoliciesAvailableDefinition(); + } + + if (suggestion === DynamicAutocompleteItem.PolicyFieldIdentifier) { + dynamicItems = buildFieldsDefinitions( + (await this.callbacks?.getPolicyFieldsIdentifiers?.(ctx)) || [] + ); + } + + if (suggestion === DynamicAutocompleteItem.PolicyMatchingFieldIdentifier) { + const [fields = [], matchingField] = await Promise.all([ + this.callbacks?.getFieldsIdentifiers?.(ctx), + this.callbacks?.getPolicyMatchingFieldIdentifiers?.(ctx), + ]); + dynamicItems = matchingField?.length + ? buildMatchingFieldsDefinition(matchingField[0], fields) + : buildFieldsDefinitions(fields); + } + return dynamicItems; + }) + ); + + return allSuggestions.flat(); } async provideCompletionItems( @@ -72,21 +96,23 @@ export class ESQLCompletionAdapter implements monaco.languages.CompletionItemPro ): Promise { const lines = model.getLineCount(); - if ( + const currentLineChars = model.getValueInRange({ + startLineNumber: 0, + startColumn: 0, + endLineNumber: position.lineNumber, + endColumn: position.column, + }); + const wordInfo = model.getWordUntilPosition(position); + const worker = await this.worker(model.uri); + const providedSuggestions = lines !== position.lineNumber || model.getLineContent(position.lineNumber).trimEnd().length >= position.column - ) { - return emptyCompletionList; - } - - const worker = await this.worker(model.uri); - const wordInfo = model.getWordUntilPosition(position); - - const providedSuggestions = await worker.provideAutocompleteSuggestions(model.uri.toString(), { - word: wordInfo.word, - line: position.lineNumber, - index: position.column, - }); + ? await worker.provideAutocompleteSuggestionsFromString(currentLineChars) + : await worker.provideAutocompleteSuggestions(model.uri.toString(), { + word: wordInfo.word, + line: position.lineNumber, + index: position.column, + }); const withDynamicItems = providedSuggestions ? await this.injectDynamicAutocompleteItems(providedSuggestions.suggestions, { @@ -96,7 +122,6 @@ export class ESQLCompletionAdapter implements monaco.languages.CompletionItemPro : []; return { - incomplete: true, suggestions: withDynamicItems.map((i) => ({ ...i, range: { diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts index 94c3c6bbe6897..6fc6caee2886f 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts @@ -27,7 +27,6 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ 'explain', 'row', 'limit', - 'project', 'ws', 'assign', 'comma', @@ -55,25 +54,48 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ ...buildRuleGroup( [ 'from', + 'metadata', + 'mv_expand', 'stats', + 'dissect', + 'grok', + 'project', + 'keep', + 'rename', + 'drop', 'eval', 'sort', 'by', 'where', + 'not', + 'is', + 'like', + 'rlike', + 'in', + 'as', 'expr_ws', 'row', + 'show', 'limit', + 'cidr_match', 'nulls_ordering_direction', 'nulls_ordering', 'null', 'boolean_value', 'comparison_operator', + 'enrich', + 'on', + 'with', ], euiThemeVars.euiColorPrimaryText ), - // math functions + // aggregation functions ...buildRuleGroup(['unary_function'], euiThemeVars.euiColorPrimaryText), + // is null functions + ...buildRuleGroup(['where_functions'], euiThemeVars.euiColorPrimaryText), + // math functions + ...buildRuleGroup(['math_function'], euiThemeVars.euiColorPrimaryText), // operators ...buildRuleGroup( diff --git a/packages/kbn-monaco/src/esql/worker/esql_worker.ts b/packages/kbn-monaco/src/esql/worker/esql_worker.ts index 4d52c2b1094cb..4656ac9e9db7c 100644 --- a/packages/kbn-monaco/src/esql/worker/esql_worker.ts +++ b/packages/kbn-monaco/src/esql/worker/esql_worker.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { CharStreams } from 'antlr4ts'; +import { CharStreams, type CodePointCharStream } from 'antlr4ts'; import { monaco } from '../../monaco_imports'; import { AutocompleteListener } from '../lib/autocomplete/autocomplete_listener'; import type { BaseWorkerDefinition } from '../../types'; @@ -43,16 +43,9 @@ export class ESQLWorker implements BaseWorkerDefinition { return []; } - public async provideAutocompleteSuggestions( - modelUri: string, - meta: { - word: string; - line: number; - index: number; - } + private async provideAutocompleteSuggestionFromRawString( + inputStream: CodePointCharStream | undefined ) { - const inputStream = this.getModelCharStream(modelUri); - if (inputStream) { const errorListener = new ANTLREErrorListener(); const parseListener = new AutocompleteListener(); @@ -63,4 +56,19 @@ export class ESQLWorker implements BaseWorkerDefinition { return parseListener.getAutocompleteSuggestions(); } } + + public async provideAutocompleteSuggestions( + modelUri: string, + meta: { + word: string; + line: number; + index: number; + } + ) { + return this.provideAutocompleteSuggestionFromRawString(this.getModelCharStream(modelUri)); + } + + public async provideAutocompleteSuggestionsFromString(text: string) { + return this.provideAutocompleteSuggestionFromRawString(CharStreams.fromString(text)); + } } diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 536b3f883cac6..a3bee52c09267 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -28,7 +28,7 @@ pageLoadAssetSize: dashboard: 82025 dashboardEnhanced: 65646 data: 454087 - dataViewEditor: 13000 + dataViewEditor: 28082 dataViewFieldEditor: 27000 dataViewManagement: 5000 dataViews: 47000 @@ -36,7 +36,6 @@ pageLoadAssetSize: devTools: 38637 discover: 99999 discoverEnhanced: 42730 - discoverLogExplorer: 39045 embeddable: 87309 embeddableEnhanced: 22107 enterpriseSearch: 50858 @@ -87,6 +86,7 @@ pageLoadAssetSize: licenseManagement: 41817 licensing: 29004 lists: 22900 + logExplorer: 39045 logsShared: 281060 logstash: 53548 management: 46112 @@ -96,8 +96,10 @@ pageLoadAssetSize: monitoring: 80000 navigation: 37269 newsfeed: 42228 + noDataPage: 5000 observability: 115443 observabilityAIAssistant: 25000 + observabilityLogExplorer: 23686 observabilityOnboarding: 19573 observabilityShared: 52256 osquery: 107090 @@ -120,7 +122,7 @@ pageLoadAssetSize: security: 81771 securitySolution: 66738 securitySolutionEss: 16573 - securitySolutionServerless: 40000 + securitySolutionServerless: 45000 serverless: 16573 serverlessObservability: 68747 serverlessSearch: 71995 @@ -140,6 +142,7 @@ pageLoadAssetSize: triggersActionsUi: 135613 uiActions: 35121 uiActionsEnhanced: 38494 + unifiedDocViewer: 25099 unifiedHistogram: 19928 unifiedSearch: 71059 upgradeAssistant: 81241 diff --git a/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts b/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts index e3d1ca81e2c26..7a3cf7f85ddf2 100644 --- a/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts +++ b/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts @@ -54,7 +54,8 @@ it('builds a generated plugin into a viable archive', async () => { }; expect(filterLogs(generateProc.all)).toMatchInlineSnapshot(` - " succ 🎉 + "Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/current/production.html#openssl-legacy-provider + succ 🎉 Your plugin has been created in plugins/foo_test_plugin " @@ -73,7 +74,8 @@ it('builds a generated plugin into a viable archive', async () => { ); expect(filterLogs(buildProc.all)).toMatchInlineSnapshot(` - " info deleting the build and target directories + "Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/current/production.html#openssl-legacy-provider + info deleting the build and target directories info run bazel and build required artifacts for the optimizer succ bazel run successfully and artifacts were created info running @kbn/optimizer diff --git a/packages/kbn-search-api-panels/components/code_box.tsx b/packages/kbn-search-api-panels/components/code_box.tsx index 55b8915328285..9a00bdd86e4e3 100644 --- a/packages/kbn-search-api-panels/components/code_box.tsx +++ b/packages/kbn-search-api-panels/components/code_box.tsx @@ -22,7 +22,6 @@ import { EuiThemeProvider, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { HttpStart } from '@kbn/core-http-browser'; import type { ApplicationStart } from '@kbn/core-application-browser'; import type { SharePluginStart } from '@kbn/share-plugin/public'; @@ -37,31 +36,29 @@ interface CodeBoxProps { languageType?: string; selectedLanguage: LanguageDefinition; setSelectedLanguage: (language: LanguageDefinition) => void; - http: HttpStart; - pluginId: string; + assetBasePath: string; application?: ApplicationStart; sharePlugin: SharePluginStart; - showTryInConsole: boolean; + consoleRequest?: string; } export const CodeBox: React.FC = ({ application, codeSnippet, - http, languageType, languages, - pluginId, + assetBasePath, selectedLanguage, setSelectedLanguage, sharePlugin, - showTryInConsole, + consoleRequest, }) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); const items = languages.map((language) => ( { setSelectedLanguage(language); setIsPopoverOpen(false); @@ -115,10 +112,10 @@ export const CodeBox: React.FC = ({ )} - {showTryInConsole && ( + {consoleRequest !== undefined && ( diff --git a/packages/kbn-search-api-panels/components/github_link.tsx b/packages/kbn-search-api-panels/components/github_link.tsx index 19c7a83ed2de3..d0b41e21daeaf 100644 --- a/packages/kbn-search-api-panels/components/github_link.tsx +++ b/packages/kbn-search-api-panels/components/github_link.tsx @@ -9,18 +9,16 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText, EuiLink } from '@elastic/eui'; -import { HttpStart } from '@kbn/core-http-browser'; export const GithubLink: React.FC<{ + assetBasePath: string; label: string; href: string; - http: HttpStart; - pluginId: string; -}> = ({ label, href, http, pluginId }) => { +}> = ({ assetBasePath, label, href }) => { return ( - + diff --git a/packages/kbn-search-api-panels/components/ingest_data.tsx b/packages/kbn-search-api-panels/components/ingest_data.tsx index 9f82b91e76159..d25f7a74d05e3 100644 --- a/packages/kbn-search-api-panels/components/ingest_data.tsx +++ b/packages/kbn-search-api-panels/components/ingest_data.tsx @@ -10,7 +10,6 @@ import React, { useState } from 'react'; import { EuiCheckableCard, EuiFormFieldset, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { HttpStart } from '@kbn/core-http-browser'; import type { ApplicationStart } from '@kbn/core-application-browser'; import type { SharePluginStart } from '@kbn/share-plugin/public'; import { CodeBox } from './code_box'; @@ -22,13 +21,17 @@ interface IngestDataProps { codeSnippet: string; selectedLanguage: LanguageDefinition; setSelectedLanguage: (language: LanguageDefinition) => void; - docLinks: any; - http: HttpStart; - pluginId: string; + docLinks: { + beats: string; + connectors: string; + integrations: string; + logstash: string; + }; + assetBasePath: string; application?: ApplicationStart; sharePlugin: SharePluginStart; languages: LanguageDefinition[]; - showTryInConsole: boolean; + consoleRequest?: string; } export const IngestData: React.FC = ({ @@ -36,12 +39,11 @@ export const IngestData: React.FC = ({ selectedLanguage, setSelectedLanguage, docLinks, - http, - pluginId, + assetBasePath, application, sharePlugin, languages, - showTryInConsole, + consoleRequest, }) => { const [selectedIngestMethod, setSelectedIngestMethod] = useState< 'ingestViaApi' | 'ingestViaIntegration' @@ -55,18 +57,17 @@ export const IngestData: React.FC = ({ leftPanelContent={ selectedIngestMethod === 'ingestViaApi' ? ( ) : ( - + ) } links={[ diff --git a/packages/kbn-search-api-panels/components/install_client.tsx b/packages/kbn-search-api-panels/components/install_client.tsx index 2f2cabb70b46e..6d56f69e09530 100644 --- a/packages/kbn-search-api-panels/components/install_client.tsx +++ b/packages/kbn-search-api-panels/components/install_client.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { EuiSpacer, EuiCallOut, EuiText, EuiPanelProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { HttpStart } from '@kbn/core-http-browser'; import type { ApplicationStart } from '@kbn/core-application-browser'; import type { SharePluginStart } from '@kbn/share-plugin/public'; import { CodeBox } from './code_box'; @@ -20,11 +19,10 @@ import { GithubLink } from './github_link'; interface InstallClientProps { codeSnippet: string; - showTryInConsole: boolean; + consoleRequest?: string; language: LanguageDefinition; setSelectedLanguage: (language: LanguageDefinition) => void; - http: HttpStart; - pluginId: string; + assetBasePath: string; application?: ApplicationStart; sharePlugin: SharePluginStart; isPanelLeft?: boolean; @@ -32,18 +30,16 @@ interface InstallClientProps { overviewPanelProps?: Partial; } -const Link: React.FC<{ language: LanguageDefinition; http: HttpStart; pluginId: string }> = ({ +const Link: React.FC<{ language: LanguageDefinition; assetBasePath: string }> = ({ language, - http, - pluginId, + assetBasePath, }) => { if (language.github) { return ( ); } @@ -52,12 +48,11 @@ const Link: React.FC<{ language: LanguageDefinition; http: HttpStart; pluginId: export const InstallClientPanel: React.FC = ({ codeSnippet, - showTryInConsole, + consoleRequest, language, languages, setSelectedLanguage, - http, - pluginId, + assetBasePath, application, sharePlugin, isPanelLeft = true, @@ -66,19 +61,18 @@ export const InstallClientPanel: React.FC = ({ const panelContent = ( <> - + = ({ docLinks, - http, - pluginId, + assetBasePath, }) => { return ( @@ -64,7 +61,7 @@ export const IntegrationsPanel: React.FC = ({ - + {LEARN_MORE_LABEL} @@ -75,8 +72,7 @@ export const IntegrationsPanel: React.FC = ({ label={i18n.translate('searchApiPanels.welcomeBanner.ingestData.logstashLink', { defaultMessage: 'Logstash', })} - http={http} - pluginId={pluginId} + assetBasePath={assetBasePath} /> @@ -117,8 +113,7 @@ export const IntegrationsPanel: React.FC = ({ label={i18n.translate('searchApiPanels.welcomeBanner.ingestData.beatsLink', { defaultMessage: 'beats', })} - http={http} - pluginId={pluginId} + assetBasePath={assetBasePath} /> @@ -162,8 +157,7 @@ export const IntegrationsPanel: React.FC = ({ defaultMessage: 'connectors-python', } )} - http={http} - pluginId={pluginId} + assetBasePath={assetBasePath} /> diff --git a/packages/kbn-search-api-panels/components/language_client_panel.tsx b/packages/kbn-search-api-panels/components/language_client_panel.tsx index 1a2cdab27a35c..9940e7a6fed10 100644 --- a/packages/kbn-search-api-panels/components/language_client_panel.tsx +++ b/packages/kbn-search-api-panels/components/language_client_panel.tsx @@ -18,8 +18,6 @@ import { useEuiTheme, } from '@elastic/eui'; -import type { HttpStart } from '@kbn/core-http-browser'; - import { LanguageDefinition } from '../types'; import './select_client.scss'; @@ -27,8 +25,7 @@ interface SelectClientProps { language: LanguageDefinition; setSelectedLanguage: (language: LanguageDefinition) => void; isSelectedLanguage: boolean; - http: HttpStart; - pluginId?: string; + assetBasePath?: string; src?: string; } @@ -36,8 +33,7 @@ export const LanguageClientPanel: React.FC = ({ language, setSelectedLanguage, isSelectedLanguage, - http, - pluginId, + assetBasePath, src, }) => { const { euiTheme } = useEuiTheme(); @@ -60,9 +56,7 @@ export const LanguageClientPanel: React.FC = ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/console.ts b/packages/kbn-search-api-panels/languages/console.ts similarity index 83% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/console.ts rename to packages/kbn-search-api-panels/languages/console.ts index afb685441e89f..be924d5fa3cbf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/console.ts +++ b/packages/kbn-search-api-panels/languages/console.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 { LanguageDefinition } from '@kbn/search-api-panels'; +import { LanguageDefinition } from '../types'; export const consoleDefinition: Partial = { buildSearchQuery: `POST /books/_search?pretty diff --git a/packages/kbn-search-api-panels/types.ts b/packages/kbn-search-api-panels/types.ts index a02afebef5c87..63edec82c345d 100644 --- a/packages/kbn-search-api-panels/types.ts +++ b/packages/kbn-search-api-panels/types.ts @@ -23,6 +23,7 @@ export interface LanguageDefinitionSnippetArguments { url: string; apiKey: string; indexName?: string; + cloudId?: string; } type CodeSnippet = string | ((args: LanguageDefinitionSnippetArguments) => string); diff --git a/packages/kbn-search-api-panels/utils.ts b/packages/kbn-search-api-panels/utils.ts index d6c8ba1341515..ffd81257c5a30 100644 --- a/packages/kbn-search-api-panels/utils.ts +++ b/packages/kbn-search-api-panels/utils.ts @@ -7,6 +7,7 @@ */ import { LanguageDefinition, LanguageDefinitionSnippetArguments } from './types'; +import { consoleDefinition } from './languages/console'; export const getLanguageDefinitionCodeSnippet = ( language: Partial, @@ -24,3 +25,8 @@ export const getLanguageDefinitionCodeSnippet = ( return ''; } }; + +export const getConsoleRequest = (code: keyof LanguageDefinition): string | undefined => + code in consoleDefinition && typeof consoleDefinition[code] === 'string' + ? (consoleDefinition[code] as string) + : undefined; diff --git a/packages/kbn-securitysolution-es-utils/src/transform_error/index.ts b/packages/kbn-securitysolution-es-utils/src/transform_error/index.ts index b532dc5d1b6d0..3a4386547e1c0 100644 --- a/packages/kbn-securitysolution-es-utils/src/transform_error/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/transform_error/index.ts @@ -8,6 +8,7 @@ import Boom from '@hapi/boom'; import { errors } from '@elastic/elasticsearch'; +import { ZodError } from 'zod'; import { BadRequestError } from '../bad_request_error'; export interface OutputError { @@ -21,6 +22,15 @@ export const transformError = (err: Error & Partial): Outp message: err.output.payload.message, statusCode: err.output.statusCode, }; + } else if (err instanceof ZodError) { + const message = stringifyZodError(err); + + return { + message, + // These errors can occur when handling requests after validation and can + // indicate of issues in business logic, so they are 500s instead of 400s + statusCode: 500, + }; } else { if (err.statusCode != null) { if (err.body != null && err.body.error != null) { @@ -50,3 +60,15 @@ export const transformError = (err: Error & Partial): Outp } } }; + +export function stringifyZodError(err: ZodError) { + return err.issues + .map((issue) => { + // If the path is empty, the error is for the root object + if (issue.path.length === 0) { + return issue.message; + } + return `${issue.path.join('.')}: ${issue.message}`; + }) + .join(', '); +} diff --git a/packages/kbn-securitysolution-list-api/src/api/index.ts b/packages/kbn-securitysolution-list-api/src/api/index.ts index 01a74756ce9be..98b83b6279953 100644 --- a/packages/kbn-securitysolution-list-api/src/api/index.ts +++ b/packages/kbn-securitysolution-list-api/src/api/index.ts @@ -581,6 +581,7 @@ export const getExceptionFilterFromExceptionListIds = async ({ }: GetExceptionFilterFromExceptionListIdsProps): Promise => http.fetch(INTERNAL_EXCEPTION_FILTER, { method: 'POST', + version: '1', body: JSON.stringify({ exception_list_ids: exceptionListIds, type: 'exception_list_ids', @@ -609,6 +610,7 @@ export const getExceptionFilterFromExceptions = async ({ }: GetExceptionFilterFromExceptionsProps): Promise => http.fetch(INTERNAL_EXCEPTION_FILTER, { method: 'POST', + version: '1', body: JSON.stringify({ exceptions, type: 'exception_items', diff --git a/packages/kbn-securitysolution-list-api/src/list_api/index.ts b/packages/kbn-securitysolution-list-api/src/list_api/index.ts index 81f4e9c94b3f0..5c280c7959763 100644 --- a/packages/kbn-securitysolution-list-api/src/list_api/index.ts +++ b/packages/kbn-securitysolution-list-api/src/list_api/index.ts @@ -117,6 +117,7 @@ const findListsBySize = async ({ }: ApiParams & FindListSchemaEncoded): Promise => { return http.fetch(`${INTERNAL_FIND_LISTS_BY_SIZE}`, { method: 'GET', + version: '1', query: { cursor, page, @@ -272,6 +273,7 @@ export { readListIndexWithValidation as readListIndex }; // TODO add types and validation export const readListPrivileges = async ({ http, signal }: ApiParams): Promise => http.fetch(LIST_PRIVILEGES_URL, { + version: '2023-10-31', method: 'GET', signal, }); diff --git a/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts b/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts index 32300a2e66c96..14f6201cc8283 100644 --- a/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts +++ b/packages/kbn-securitysolution-utils/src/transform_data_to_ndjson/index.test.ts @@ -20,7 +20,6 @@ const getRulesSchemaMock = (anchorDate: string = ANCHOR_DATE) => ({ enabled: true, false_positives: ['false positive 1', 'false positive 2'], from: 'now-6m', - investigation_fields: ['custom.field1', 'custom.field2'], immutable: false, name: 'Query with a rule id', query: 'user.name: root or user.name: admin', diff --git a/packages/kbn-test/index.ts b/packages/kbn-test/index.ts index f779803d794b1..5be415161a4a5 100644 --- a/packages/kbn-test/index.ts +++ b/packages/kbn-test/index.ts @@ -38,6 +38,7 @@ export { kibanaTestUser, adminTestUser, systemIndicesSuperuser, + kibanaTestSuperuserServerless, } from './src/kbn'; // @internal @@ -58,3 +59,5 @@ export * from './src/kbn_archiver_cli'; export * from './src/kbn_client'; export * from './src/find_test_plugin_paths'; + +export { getDockerFileMountPath } from '@kbn/es'; diff --git a/packages/kbn-test/jest-preset.js b/packages/kbn-test/jest-preset.js index f80a5e103c16f..ed5a174e2db80 100644 --- a/packages/kbn-test/jest-preset.js +++ b/packages/kbn-test/jest-preset.js @@ -105,8 +105,10 @@ module.exports = { transformIgnorePatterns: [ // ignore all node_modules except monaco-editor and react-monaco-editor which requires babel transforms to handle dynamic import() // since ESM modules are not natively supported in Jest yet (https://github.com/facebook/jest/issues/4842) - '[/\\\\]node_modules(?![\\/\\\\](byte-size|monaco-editor|monaco-yaml|vscode-languageserver-types|react-monaco-editor|d3-interpolate|d3-color))[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](byte-size|monaco-editor|monaco-yaml|vscode-languageserver-types|react-monaco-editor|d3-interpolate|d3-color|langchain|langsmith|@cfworker))[/\\\\].+\\.js$', 'packages/kbn-pm/dist/index.js', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/util/[/\\\\].+\\.js$', ], // An array of regexp pattern strings that are matched against all source file paths, matched files to include/exclude for code coverage diff --git a/packages/kbn-test/jest_integration_node/jest-preset.js b/packages/kbn-test/jest_integration_node/jest-preset.js index 43373e41db5c1..92b8aedb5ee88 100644 --- a/packages/kbn-test/jest_integration_node/jest-preset.js +++ b/packages/kbn-test/jest_integration_node/jest-preset.js @@ -19,6 +19,13 @@ module.exports = { testPathIgnorePatterns: preset.testPathIgnorePatterns.filter( (pattern) => !pattern.includes('integration_tests') ), + // An array of regexp pattern strings that are matched against, matched files will skip transformation: + transformIgnorePatterns: [ + // since ESM modules are not natively supported in Jest yet (https://github.com/facebook/jest/issues/4842) + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](langchain|langsmith))/dist/util/[/\\\\].+\\.js$', + ], setupFilesAfterEnv: [ '/packages/kbn-test/src/jest/setup/after_env.integration.js', '/packages/kbn-test/src/jest/setup/mocks.moment_timezone.js', diff --git a/packages/kbn-test/kbn_test_config.ts b/packages/kbn-test/kbn_test_config.ts index 1e656f3347909..7a4d868d324a5 100644 --- a/packages/kbn-test/kbn_test_config.ts +++ b/packages/kbn-test/kbn_test_config.ts @@ -18,12 +18,17 @@ export interface UrlParts { password?: string; } +interface UserAuth { + username: string; + password: string; +} + export const kbnTestConfig = new (class KbnTestConfig { getPort() { return this.getUrlParts().port; } - getUrlParts(): UrlParts { + getUrlParts(user: UserAuth = kibanaTestUser): UrlParts { // allow setting one complete TEST_KIBANA_URL for ES like https://elastic:changeme@example.com:9200 if (process.env.TEST_KIBANA_URL) { const testKibanaUrl = url.parse(process.env.TEST_KIBANA_URL); @@ -37,8 +42,8 @@ export const kbnTestConfig = new (class KbnTestConfig { }; } - const username = process.env.TEST_KIBANA_USERNAME || kibanaTestUser.username; - const password = process.env.TEST_KIBANA_PASSWORD || kibanaTestUser.password; + const username = process.env.TEST_KIBANA_USERNAME || user.username; + const password = process.env.TEST_KIBANA_PASSWORD || user.password; return { protocol: process.env.TEST_KIBANA_PROTOCOL || 'http', hostname: process.env.TEST_KIBANA_HOSTNAME || 'localhost', diff --git a/packages/kbn-test/src/es/test_es_cluster.ts b/packages/kbn-test/src/es/test_es_cluster.ts index 9b2a3b8010be2..580840b6b35a8 100644 --- a/packages/kbn-test/src/es/test_es_cluster.ts +++ b/packages/kbn-test/src/es/test_es_cluster.ts @@ -143,6 +143,14 @@ export interface CreateTestEsClusterOptions { * this caller to react appropriately. If this is not passed then an uncatchable exception will be thrown */ onEarlyExit?: (msg: string) => void; + /** + * Is this a serverless project + */ + serverless?: boolean; + /** + * Files to mount inside ES containers + */ + files?: string[]; } export function createTestEsCluster< @@ -164,6 +172,7 @@ export function createTestEsCluster< ssl, transportPort, onEarlyExit, + files, } = options; const clusterName = `${CI_PARALLEL_PROCESS_PREFIX}${customClusterName}`; @@ -218,6 +227,18 @@ export function createTestEsCluster< installPath = (await firstNode.installSource(config)).installPath; } else if (esFrom === 'snapshot') { installPath = (await firstNode.installSnapshot(config)).installPath; + } else if (esFrom === 'serverless') { + return await firstNode.runServerless({ + basePath, + esArgs: customEsArgs, + port, + clean: true, + teardown: true, + ssl: true, + background: true, + files, + kill: true, // likely don't need this but avoids any issues where the ESS cluster wasn't cleaned up + }); } else if (Path.isAbsolute(esFrom)) { installPath = esFrom; } else { diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index 03c0cbc07e644..27bdee55da128 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -210,6 +210,7 @@ export const schema = Joi.object() scheme: /https?/, }), }), + files: Joi.array().items(Joi.string()), }) .default(), diff --git a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts index 40d4da7d76d76..09e251d70a25b 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts +++ b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts @@ -46,6 +46,8 @@ function getEsConfig({ : config.get('servers.elasticsearch.password'); const dataArchive: string | undefined = config.get('esTestCluster.dataArchive'); + const serverless: boolean = config.get('serverless'); + const files: string[] | undefined = config.get('esTestCluster.files'); return { ssl, @@ -58,6 +60,8 @@ function getEsConfig({ password, dataArchive, ccsConfig, + serverless, + files, }; } @@ -140,6 +144,8 @@ async function startEsNode({ ], transportPort: config.transportPort, onEarlyExit, + serverless: config.serverless, + files: config.files, }); await cluster.start(); diff --git a/packages/kbn-test/src/functional_tests/run_tests/flags.test.ts b/packages/kbn-test/src/functional_tests/run_tests/flags.test.ts index dbb8b1e9762e5..0c9dae3a25794 100644 --- a/packages/kbn-test/src/functional_tests/run_tests/flags.test.ts +++ b/packages/kbn-test/src/functional_tests/run_tests/flags.test.ts @@ -41,7 +41,7 @@ describe('parse runTest flags', () => { /foo, ], "dryRun": false, - "esFrom": "snapshot", + "esFrom": undefined, "esVersion": , "grep": undefined, "installDir": undefined, @@ -108,7 +108,7 @@ describe('parse runTest flags', () => { it('validates esFrom', () => { expect(() => test({ esFrom: 'foo' })).toThrowErrorMatchingInlineSnapshot( - `"invalid --esFrom, expected one of \\"snapshot\\", \\"source\\""` + `"invalid --esFrom, expected one of \\"snapshot\\", \\"source\\", \\"serverless\\""` ); }); diff --git a/packages/kbn-test/src/functional_tests/run_tests/flags.ts b/packages/kbn-test/src/functional_tests/run_tests/flags.ts index 9f91bf2728cbe..f4dd6beb26e80 100644 --- a/packages/kbn-test/src/functional_tests/run_tests/flags.ts +++ b/packages/kbn-test/src/functional_tests/run_tests/flags.ts @@ -36,7 +36,7 @@ export const FLAG_OPTIONS: FlagOptions = { help: ` --config Define a FTR config that should be executed. Can be specified multiple times --journey Define a Journey that should be executed. Can be specified multiple times - --esFrom Build Elasticsearch from source or run from snapshot. Default: $TEST_ES_FROM or "snapshot" + --esFrom Build Elasticsearch from source or run snapshot or serverless. Default: $TEST_ES_FROM or "snapshot" --include-tag Tags that suites must include to be run, can be included multiple times --exclude-tag Tags that suites must NOT include to be run, can be included multiple times --include Files that must included to be run, can be included multiple times @@ -74,7 +74,7 @@ export function parseFlags(flags: FlagsReader) { logsDir: flags.boolean('logToFile') ? Path.resolve(REPO_ROOT, 'data/ftr_servers_logs', uuidV4()) : undefined, - esFrom: flags.enum('esFrom', ['snapshot', 'source']) ?? 'snapshot', + esFrom: flags.enum('esFrom', ['snapshot', 'source', 'serverless']), installDir: flags.path('kibana-install-dir'), grep: flags.string('grep'), suiteTags: { diff --git a/packages/kbn-test/src/functional_tests/run_tests/run_tests.ts b/packages/kbn-test/src/functional_tests/run_tests/run_tests.ts index b8edfeadbdf08..81c0039001197 100644 --- a/packages/kbn-test/src/functional_tests/run_tests/run_tests.ts +++ b/packages/kbn-test/src/functional_tests/run_tests/run_tests.ts @@ -42,6 +42,9 @@ export async function runTests(log: ToolingLog, options: RunTestsOptions) { dryRun: options.dryRun, grep: options.grep, }, + esTestCluster: { + from: options.esFrom, + }, kbnTestServer: { installDir: options.installDir, }, diff --git a/packages/kbn-test/src/functional_tests/start_servers/flags.ts b/packages/kbn-test/src/functional_tests/start_servers/flags.ts index 0f53ca6866fa8..ad2a143f6db7a 100644 --- a/packages/kbn-test/src/functional_tests/start_servers/flags.ts +++ b/packages/kbn-test/src/functional_tests/start_servers/flags.ts @@ -23,7 +23,7 @@ export const FLAG_OPTIONS: FlagOptions = { help: ` --config Define a FTR config that should be executed. Can be specified multiple times --journey Define a Journey that should be executed. Can be specified multiple times - --esFrom Build Elasticsearch from source or run from snapshot. Default: $TEST_ES_FROM or "snapshot" + --esFrom Build Elasticsearch from source or run snapshot or serverless. Default: $TEST_ES_FROM or "snapshot" --kibana-install-dir Run Kibana from existing install directory instead of from source --logToFile Write the log output from Kibana/ES to files instead of to stdout `, @@ -40,7 +40,7 @@ export function parseFlags(flags: FlagsReader) { return { config: configs[0], - esFrom: flags.enum('esFrom', ['source', 'snapshot']), + esFrom: flags.enum('esFrom', ['source', 'snapshot', 'serverless']), esVersion: EsVersion.getDefault(), installDir: flags.string('kibana-install-dir'), logsDir: flags.boolean('logToFile') diff --git a/packages/kbn-test/src/jest/setup/setup_test.js b/packages/kbn-test/src/jest/setup/setup_test.js index b0038daf196c9..ee386f894a71e 100644 --- a/packages/kbn-test/src/jest/setup/setup_test.js +++ b/packages/kbn-test/src/jest/setup/setup_test.js @@ -13,6 +13,7 @@ import 'jest-styled-components'; import '@testing-library/jest-dom'; +import 'web-streams-polyfill/es6'; // ReadableStream polyfill /** * Removed in Jest 27/jsdom, used in some transitive dependencies diff --git a/packages/kbn-test/src/kbn/index.ts b/packages/kbn-test/src/kbn/index.ts index cf0cac046a8fa..6f2c009ce7370 100644 --- a/packages/kbn-test/src/kbn/index.ts +++ b/packages/kbn-test/src/kbn/index.ts @@ -11,4 +11,5 @@ export { kibanaServerTestUser, adminTestUser, systemIndicesSuperuser, + kibanaTestSuperuserServerless, } from './users'; diff --git a/packages/kbn-test/src/kbn/users.ts b/packages/kbn-test/src/kbn/users.ts index b0db9e88ffc40..9a68a55beb6eb 100644 --- a/packages/kbn-test/src/kbn/users.ts +++ b/packages/kbn-test/src/kbn/users.ts @@ -6,7 +6,11 @@ * Side Public License, v 1. */ -import { SYSTEM_INDICES_SUPERUSER } from '@kbn/es'; +import { + SYSTEM_INDICES_SUPERUSER, + ELASTIC_SERVERLESS_SUPERUSER, + ELASTIC_SERVERLESS_SUPERUSER_PASSWORD, +} from '@kbn/es'; const env = process.env; @@ -32,3 +36,8 @@ export const systemIndicesSuperuser = { username: SYSTEM_INDICES_SUPERUSER, password: env.TEST_ES_PASS || 'changeme', }; + +export const kibanaTestSuperuserServerless = { + username: ELASTIC_SERVERLESS_SUPERUSER, + password: ELASTIC_SERVERLESS_SUPERUSER_PASSWORD, +}; diff --git a/packages/kbn-text-based-editor/src/__stories__/text_based_editor.stories.mdx b/packages/kbn-text-based-editor/src/__stories__/text_based_editor.stories.mdx index 0874305b1975b..f6e0a751e7755 100644 --- a/packages/kbn-text-based-editor/src/__stories__/text_based_editor.stories.mdx +++ b/packages/kbn-text-based-editor/src/__stories__/text_based_editor.stories.mdx @@ -31,7 +31,7 @@ The TextBasedLanguagesEditor component is a reusable component and can be used t name='compact mode' args={ { - query: { sql: 'SELECT field1, field2 FROM DATAVIEW' }, + query: { esql: 'from dataview | keep field1, field2' }, isCodeEditorExpanded:false, 'data-test-subj':'test-id' } @@ -51,7 +51,7 @@ When there are errors to the query the UI displays the errors to the editor: name='with errors' args={ { - query: { sql: 'SELECT field1, field2 FROM DATAVIEW' }, + query: { esql: 'from dataview | keep field1, field2' }, isCodeEditorExpanded:false, 'data-test-subj':'test-id', errors: [ @@ -76,7 +76,7 @@ When there the query is long and the editor is on the compact view: name='with long query' args={ { - query: { sql: 'SELECT field1, field2, field 3, field 4, field 5 FROM DATAVIEW WHERE field5 IS NOT NULL AND field4 IS NULL' }, + query: { esql: 'from dataview | keep field1, field2, field 3, field 4, field 5 | where field5 > 5 | stats var = avg(field3)' }, isCodeEditorExpanded:false, 'data-test-subj':'test-id', } @@ -97,7 +97,7 @@ The editor also works on the expanded mode: name='on expanded mode' args={ { - query: { sql: 'SELECT field1, field2 FROM DATAVIEW' }, + query: { esql: 'from dataview | keep field1, field2' }, isCodeEditorExpanded:true, 'data-test-subj':'test-id', } @@ -110,6 +110,27 @@ The editor also works on the expanded mode: +The editor also works on the expanded mode with the minimize button hidden: + + + + {Template.bind({})} + + + ## Component props The component exposes the following properties: diff --git a/packages/kbn-text-based-editor/src/editor_footer.tsx b/packages/kbn-text-based-editor/src/editor_footer.tsx index 3119d548098de..6f1e6cdd0b130 100644 --- a/packages/kbn-text-based-editor/src/editor_footer.tsx +++ b/packages/kbn-text-based-editor/src/editor_footer.tsx @@ -28,10 +28,130 @@ import type { MonacoError } from './helpers'; const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0; const COMMAND_KEY = isMac ? '⌘' : '^'; +const getConstsByType = (type: 'error' | 'warning', count: number) => { + if (type === 'error') { + return { + color: 'danger', + message: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.errorCount', { + defaultMessage: '{count} {count, plural, one {error} other {errors}}', + values: { count }, + }), + label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.errorsTitle', { + defaultMessage: 'Errors', + }), + }; + } else { + return { + color: 'warning', + message: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.warningCount', { + defaultMessage: '{count} {count, plural, one {warning} other {warnings}}', + values: { count }, + }), + label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.warningsTitle', { + defaultMessage: 'Warnings', + }), + }; + } +}; + +export function ErrorsWarningsPopover({ + isPopoverOpen, + items, + type, + refreshErrors, + setIsPopoverOpen, + onErrorClick, +}: { + isPopoverOpen: boolean; + items: MonacoError[]; + type: 'error' | 'warning'; + refreshErrors: () => void; + setIsPopoverOpen: (flag: boolean) => void; + onErrorClick: (error: MonacoError) => void; +}) { + const strings = getConstsByType(type, items.length); + return ( + + + + + + + { + refreshErrors(); + setIsPopoverOpen(!isPopoverOpen); + }} + > +

    {strings.message}

    + + } + ownFocus={false} + isOpen={isPopoverOpen} + closePopover={() => setIsPopoverOpen(false)} + > +
    + {strings.label} + + {items.map((item, index) => { + return ( + onErrorClick(item)} + > + + + + + + + + {i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.lineNumber', + { + defaultMessage: 'Line {lineNumber}', + values: { lineNumber: item.startLineNumber }, + } + )} + + + + + {item.message} + + + + ); + })} + +
    +
    +
    +
    +
    + ); +} + interface EditorFooterProps { lines: number; containerCSS: Interpolation; errors?: MonacoError[]; + warning?: MonacoError[]; detectTimestamp: boolean; onErrorClick: (error: MonacoError) => void; refreshErrors: () => void; @@ -41,6 +161,7 @@ export const EditorFooter = memo(function EditorFooter({ lines, containerCSS, errors, + warning, detectTimestamp, onErrorClick, refreshErrors, @@ -57,97 +178,24 @@ export const EditorFooter = memo(function EditorFooter({ {errors && errors.length > 0 && ( - - - - - - - { - refreshErrors(); - setIsPopoverOpen(!isPopoverOpen); - }} - > -

    - {i18n.translate( - 'textBasedEditor.query.textBasedLanguagesEditor.errorCount', - { - defaultMessage: '{count} {count, plural, one {error} other {errors}}', - values: { count: errors.length }, - } - )} -

    - - } - ownFocus={false} - isOpen={isPopoverOpen} - closePopover={() => setIsPopoverOpen(false)} - > -
    - - {i18n.translate( - 'textBasedEditor.query.textBasedLanguagesEditor.errorsTitle', - { - defaultMessage: 'Errors', - } - )} - - - {errors.map((error, index) => { - return ( - onErrorClick(error)} - > - - - - - - - - {i18n.translate( - 'textBasedEditor.query.textBasedLanguagesEditor.lineNumber', - { - defaultMessage: 'Line {lineNumber}', - values: { lineNumber: error.startLineNumber }, - } - )} - - - - - {error.message} - - - - ); - })} - -
    -
    -
    -
    -
    + + )} + {warning && warning.length > 0 && ( + )} diff --git a/packages/kbn-text-based-editor/src/esql_documentation_sections.tsx b/packages/kbn-text-based-editor/src/esql_documentation_sections.tsx new file mode 100644 index 0000000000000..a3b4ef893a771 --- /dev/null +++ b/packages/kbn-text-based-editor/src/esql_documentation_sections.tsx @@ -0,0 +1,2318 @@ +/* + * Copyright 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 { i18n } from '@kbn/i18n'; +import { Markdown } from '@kbn/kibana-react-plugin/public'; + +export const initialSection = ( + +); + +export const sourceCommands = { + label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.sourceCommands', { + defaultMessage: 'Source commands', + }), + description: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.commandsDescription', + { + defaultMessage: `A source command produces a table, typically with data from Elasticsearch. ES|QL supports the following source commands.`, + } + ), + items: [ + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.from', + { + defaultMessage: 'FROM', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.row', + { + defaultMessage: 'ROW', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.show', + { + defaultMessage: 'SHOW', + } + ), + description: ( + \` source command returns information about the deployment and its capabilities: + +* Use \`SHOW INFO\` to return the deployment's version, build date and hash. +* Use \`SHOW FUNCTIONS\` to return a list of all supported functions and a synopsis of each function. + `, + description: + 'Text is in markdown. Do not translate function names, special characters, or field names like sum(bytes)', + } + )} + /> + ), + }, + ], +}; + +export const processingCommands = { + label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.processingCommands', { + defaultMessage: 'Processing commands', + }), + description: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.processingCommandsDescription', + { + defaultMessage: `Processing commands change an input table by adding, removing, or changing rows and columns. ES|QL supports the following processing commands.`, + } + ), + items: [ + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.dissect', + { + defaultMessage: 'DISSECT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.drop', + { + defaultMessage: 'DROP', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.enrich', + { + defaultMessage: 'ENRICH', + } + ), + description: ( + \`; if it’s not specified, the match will be performed on a field with the same name as the match field defined in the enrich policy. + +\`\`\` +ROW a = "1" +| ENRICH languages_policy ON a +\`\`\` + +You can specify which attributes (between those defined as enrich fields in the policy) have to be added to the result, using \`WITH , ...\` syntax. + +\`\`\` +ROW a = "1" +| ENRICH languages_policy ON a WITH language_name +\`\`\` + +Attributes can also be renamed using \`WITH new_name=\` + +\`\`\` +ROW a = "1" +| ENRICH languages_policy ON a WITH name = language_name +\`\`\` + +By default (if no \`WITH\` is defined), \`ENRICH\` will add all the enrich fields defined in the enrich policy to the result. + +In case of name collisions, the newly created fields will override the existing fields. + `, + description: + 'Text is in markdown. Do not translate function names, special characters, or field names like sum(bytes)', + } + )} + /> + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.eval', + { + defaultMessage: 'EVAL', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.grok', + { + defaultMessage: 'GROK', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.keep', + { + defaultMessage: 'KEEP', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.limit', + { + defaultMessage: 'LIMIT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvExpand', + { + defaultMessage: 'MV_EXPAND', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.rename', + { + defaultMessage: 'RENAME', + } + ), + description: ( + = +\`\`\` + +For example: + +\`\`\` +FROM employees +| KEEP first_name, last_name, still_hired +| RENAME employed = still_hired +\`\`\` + +If a column with the new name already exists, it will be replaced by the new column. + +Multiple columns can be renamed with a single \`RENAME\` command: + +\`\`\` +FROM employees +| KEEP first_name, last_name +| RENAME fn = first_name, ln = last_name +\`\`\` + `, + description: + 'Text is in markdown. Do not translate function names, special characters, or field names like sum(bytes)', + } + )} + /> + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sort', + { + defaultMessage: 'SORT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.statsby', + { + defaultMessage: 'STATS ... BY', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.where', + { + defaultMessage: 'WHERE', + } + ), + description: ( + \` +* larger than or equal: \`>=\` + +The \`IN\` operator allows testing whether a field or expression equals an element in a list of literals, fields or expressions: + +\`\`\` +ROW a = 1, b = 4, c = 3 +| WHERE c-a IN (3, b / 2, a) +\`\`\` + +For string comparison using wildcards or regular expressions, use \`LIKE\` or \`RLIKE\`: + +* Use \`LIKE\` to match strings using wildcards. The following wildcard characters are supported: + * \`*\` matches zero or more characters. + * \`?\` matches one character. + + \`\`\` + FROM employees + | WHERE first_name LIKE "?b*" + | KEEP first_name, last_name + \`\`\` + +* Use \`RLIKE\` to match strings using [regular expressions](https://www.elastic.co/guide/en/elasticsearch/reference/current/regexp-syntax.html): + + \`\`\` + FROM employees + | WHERE first_name RLIKE ".leja.*" + | KEEP first_name, last_name + \`\`\` + +You can use the following boolean operators: + +* \`AND\` +* \`OR\` +* \`NOT\` + +\`\`\` +FROM employees +| KEEP first_name, last_name, height, still_hired +| WHERE height > 2 AND NOT still_hired +\`\`\` + +#### Functions +\`WHERE\` supports various functions for calculating values. Refer to Functions for more information. + `, + description: + 'Text is in markdown. Do not translate function names, special characters, or field names like sum(bytes)', + } + )} + /> + ), + }, + ], +}; + +export const functions = { + label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.functions', { + defaultMessage: 'Functions', + }), + description: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.functionsDocumentationESQLDescription', + { + defaultMessage: `Functions are supported by ROW, EVAL and WHERE.`, + } + ), + items: [ + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.absFunction', + { + defaultMessage: 'ABS', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.autoBucketFunction', + { + defaultMessage: 'AUTO_BUCKET', + } + ), + description: ( + = "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z" +| EVAL bucket = AUTO_BUCKET(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z") +| STATS AVG(salary) BY bucket +| SORT bucket +\`\`\` + +Returning: +\`\`\` +46305.0 | 1985-02-01T00:00:00.000Z +44817.0 | 1985-05-01T00:00:00.000Z +62405.0 | 1985-07-01T00:00:00.000Z +49095.0 | 1985-09-01T00:00:00.000Z +51532.0 | 1985-10-01T00:00:00.000Z +54539.75 | 1985-11-01T00:00:00.000 +\`\`\` + +NOTE: \`AUTO_BUCKET\` does not create buckets that don’t match any documents. That’s why the example above is missing 1985-03-01 and other dates. + `, + description: + 'Text is in markdown. Do not translate function names, special characters, or field names like sum(bytes)', + } + )} + /> + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.caseFunction', + { + defaultMessage: 'CASE', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.cidrMatchFunction', + { + defaultMessage: 'CIDR_MATCH', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.concatFunction', + { + defaultMessage: 'CONCAT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.dateFormatFunction', + { + defaultMessage: 'DATE_FORMAT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.dateTruncFunction', + { + defaultMessage: 'DATE_TRUNC', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.eFunction', + { + defaultMessage: 'E', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.isFiniteFunction', + { + defaultMessage: 'IS_FINITE', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.isInfiniteFunction', + { + defaultMessage: 'IS_INFINITE', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.isNanFunction', + { + defaultMessage: 'IS_NAN', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.isNullFunction', + { + defaultMessage: 'IS_NULL', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.lengthFunction', + { + defaultMessage: 'LENGTH', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.log10Function', + { + defaultMessage: 'LOG10', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvAvgFunction', + { + defaultMessage: 'MV_AVG', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvConcatFunction', + { + defaultMessage: 'MV_CONCAT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvCountFunction', + { + defaultMessage: 'MV_COUNT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvDedupeFunction', + { + defaultMessage: 'MV_DEDUPE', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvMaxFunction', + { + defaultMessage: 'MV_MAX', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvMedianFunction', + { + defaultMessage: 'MV_MEDIAN', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvMinFunction', + { + defaultMessage: 'MV_MIN', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.mvSumFunction', + { + defaultMessage: 'MV_SUM', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.piFunction', + { + defaultMessage: 'PI', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.powFunction', + { + defaultMessage: 'POW', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.roundFunction', + { + defaultMessage: 'ROUND', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.splitFunction', + { + defaultMessage: 'SPLIT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.startsWithFunction', + { + defaultMessage: 'STARTS_WITH', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.substringFunction', + { + defaultMessage: 'SUBSTRING', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.tauFunction', + { + defaultMessage: 'TAU', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.toBooleanFunction', + { + defaultMessage: 'TO_BOOLEAN', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.toDatetimeFunction', + { + defaultMessage: 'TO_DATETIME', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.toDoubleFunction', + { + defaultMessage: 'TO_DOUBLE', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.toIntegerFunction', + { + defaultMessage: 'TO_INTEGER', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.toIpFunction', + { + defaultMessage: 'TO_IP', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.toLongFunction', + { + defaultMessage: 'TO_LONG', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.toStringFunction', + { + defaultMessage: 'TO_STRING', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.toVersionFunction', + { + defaultMessage: 'TO_VERSION', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.trimFunction', + { + defaultMessage: 'TRIM', + } + ), + description: ( + + ), + }, + ], +}; + +export const aggregationFunctions = { + label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.aggregationFunctions', { + defaultMessage: 'Aggregation functions', + }), + description: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.aggregationFunctionsDocumentationESQLDescription', + { + defaultMessage: `These functions can by used with STATS...BY:`, + } + ), + items: [ + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.avgFunction', + { + defaultMessage: 'AVG', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.countFunction', + { + defaultMessage: 'COUNT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.countDistinctFunction', + { + defaultMessage: 'COUNT_DISTINCT', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.maxFunction', + { + defaultMessage: 'MAX', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.medianFunction', + { + defaultMessage: 'MEDIAN', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.medianAbsoluteDeviationFunction', + { + defaultMessage: 'MEDIAN_ABSOLUTE_DEVIATION', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.minFunction', + { + defaultMessage: 'MIN', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.percentileFunction', + { + defaultMessage: 'PERCENTILE', + } + ), + description: ( + + ), + }, + { + label: i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationESQL.sumFunction', + { + defaultMessage: 'SUM', + } + ), + description: ( + + ), + }, + ], +}; diff --git a/packages/kbn-text-based-editor/src/fetch_fields_from_esql.ts b/packages/kbn-text-based-editor/src/fetch_fields_from_esql.ts new file mode 100644 index 0000000000000..b847e4cb0bb43 --- /dev/null +++ b/packages/kbn-text-based-editor/src/fetch_fields_from_esql.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 { pluck } from 'rxjs/operators'; +import { lastValueFrom } from 'rxjs'; +import { Query, AggregateQuery } from '@kbn/es-query'; +import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; +import type { Datatable } from '@kbn/expressions-plugin/public'; +import { textBasedQueryStateToAstWithValidation } from '@kbn/data-plugin/common'; + +interface TextBasedLanguagesErrorResponse { + error: { + message: string; + }; + type: 'error'; +} + +export function fetchFieldsFromESQL(query: Query | AggregateQuery, expressions: ExpressionsStart) { + return textBasedQueryStateToAstWithValidation({ + query, + }) + .then((ast) => { + if (ast) { + const execution = expressions.run(ast, null); + let finalData: Datatable; + let error: string | undefined; + execution.pipe(pluck('result')).subscribe((resp) => { + const response = resp as Datatable | TextBasedLanguagesErrorResponse; + if (response.type === 'error') { + error = response.error.message; + } else { + finalData = response; + } + }); + return lastValueFrom(execution).then(() => { + if (error) { + throw new Error(error); + } else { + return finalData; + } + }); + } + return undefined; + }) + .catch((err) => { + throw new Error(err.message); + }); +} diff --git a/packages/kbn-text-based-editor/src/helpers.test.ts b/packages/kbn-text-based-editor/src/helpers.test.ts index a56d0ecee141c..74c2387fde2fa 100644 --- a/packages/kbn-text-based-editor/src/helpers.test.ts +++ b/packages/kbn-text-based-editor/src/helpers.test.ts @@ -6,11 +6,11 @@ * Side Public License, v 1. */ -import { parseErrors, getInlineEditorText } from './helpers'; +import { parseErrors, parseWarning, getInlineEditorText } from './helpers'; describe('helpers', function () { describe('parseErrors', function () { - it('should return the correct error object from SQL ES response for an one liner query', function () { + it('should return the correct error object from ESQL ES response for an one liner query', function () { const error = new Error( '[essql] > Unexpected error from Elasticsearch: verification_exception - Found 1 problem\nline 1:8: Unknown column [miaou]' ); @@ -27,7 +27,7 @@ describe('helpers', function () { ]); }); - it('should return the correct error object from SQL ES response for an multi liner query', function () { + it('should return the correct error object from ESQL ES response for an multi liner query', function () { const error = new Error( '[essql] > Unexpected error from Elasticsearch: verification_exception - Found 1 problem line 3:7: Condition expression needs to be boolean, found [TEXT]' ); @@ -54,7 +54,7 @@ describe('helpers', function () { it('should return the generic error object for an error of unknown format', function () { const error = new Error('I am an unknown error'); const errors = [error]; - expect(parseErrors(errors, `SELECT * FROM "kibana_sample_data_ecommerce"`)).toEqual([ + expect(parseErrors(errors, `FROM "kibana_sample_data_ecommerce"`)).toEqual([ { endColumn: 10, endLineNumber: 1, @@ -67,29 +67,73 @@ describe('helpers', function () { }); }); + describe('parseWarning', function () { + it('should return the correct warning object from ESQL ES response for an one liner query', function () { + const warning = + '299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Line 1:52: evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded."'; + expect(parseWarning(warning)).toEqual([ + { + endColumn: 138, + endLineNumber: 1, + message: + 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', + severity: 8, + startColumn: 52, + startLineNumber: 1, + }, + ]); + }); + + it('should return the correct array of warnings if multiple warnins are detected', function () { + const warning = + '299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Line 1:52: evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.", 299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Line 1:84: evaluation of [date_parse(geo.src)] failed, treating result as null. Only first 20 failures recorded."'; + expect(parseWarning(warning)).toEqual([ + { + endColumn: 138, + endLineNumber: 1, + message: + 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', + severity: 8, + startColumn: 52, + startLineNumber: 1, + }, + { + endColumn: 169, + endLineNumber: 1, + message: + 'evaluation of [date_parse(geo.src)] failed, treating result as null. Only first 20 failures recorded.', + severity: 8, + startColumn: 84, + startLineNumber: 1, + }, + ]); + }); + }); + describe('getInlineEditorText', function () { it('should return the entire query if it is one liner', function () { - const text = getInlineEditorText( - 'SELECT field1, count(*) FROM index1 ORDER BY field1', - false - ); + const text = getInlineEditorText('FROM index1 | keep field1, field2 | order field1', false); expect(text).toEqual(text); }); it('should return the query on one line with extra space if is multiliner', function () { const text = getInlineEditorText( - 'SELECT field1, count(*)\nFROM index1 ORDER BY field1', + 'FROM index1 | keep field1, field2\n| keep field1, field2 | order field1', true ); - expect(text).toEqual('SELECT field1, count(*) FROM index1 ORDER BY field1'); + expect(text).toEqual( + 'FROM index1 | keep field1, field2 | keep field1, field2 | order field1' + ); }); it('should return the query on one line with extra spaces removed if is multiliner', function () { const text = getInlineEditorText( - 'SELECT field1, count(*)\nFROM index1 \n ORDER BY field1', + 'FROM index1 | keep field1, field2\n| keep field1, field2 \n | order field1', true ); - expect(text).toEqual('SELECT field1, count(*) FROM index1 ORDER BY field1'); + expect(text).toEqual( + 'FROM index1 | keep field1, field2 | keep field1, field2 | order field1' + ); }); }); }); diff --git a/packages/kbn-text-based-editor/src/helpers.ts b/packages/kbn-text-based-editor/src/helpers.ts index d1deae5bf0d80..ca5e3d2fca663 100644 --- a/packages/kbn-text-based-editor/src/helpers.ts +++ b/packages/kbn-text-based-editor/src/helpers.ts @@ -42,6 +42,43 @@ export const useDebounceWithOptions = ( ); }; +export const parseWarning = (warning: string): MonacoError[] => { + if (warning.includes('Line')) { + const splitByLine = warning.split('Line'); + splitByLine.shift(); + return splitByLine.map((item) => { + const [lineNumber, startPosition, warningMessage] = item.split(':'); + const [trimmedMessage] = warningMessage.split('"'); + // initialize the length to 10 in case no error word found + let errorLength = 10; + const [_, wordWithError] = trimmedMessage.split('['); + if (wordWithError) { + errorLength = wordWithError.length - 1; + } + return { + message: trimmedMessage.trimStart(), + startColumn: Number(startPosition), + startLineNumber: Number(lineNumber), + endColumn: Number(startPosition) + errorLength, + endLineNumber: Number(lineNumber), + severity: monaco.MarkerSeverity.Error, + }; + }); + } else { + // unknown warning message + return [ + { + message: warning, + startColumn: 1, + startLineNumber: 1, + endColumn: 10, + endLineNumber: 1, + severity: monaco.MarkerSeverity.Error, + }, + ]; + } +}; + export const parseErrors = (errors: Error[], code: string): MonacoError[] => { return errors.map((error) => { if (error.message.includes('line')) { @@ -101,6 +138,21 @@ export const getDocumentationSections = async (language: string) => { initialSection, }; } + if (language === 'esql') { + const { sourceCommands, processingCommands, initialSection, functions, aggregationFunctions } = + await import('./esql_documentation_sections'); + groups.push({ + label: i18n.translate('textBasedEditor.query.textBasedLanguagesEditor.esql', { + defaultMessage: 'ES|QL', + }), + items: [], + }); + groups.push(sourceCommands, processingCommands, functions, aggregationFunctions); + return { + groups, + initialSection, + }; + } }; export const getInlineEditorText = (queryString: string, isMultiLine: boolean) => { diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.styles.ts b/packages/kbn-text-based-editor/src/text_based_languages_editor.styles.ts index 86a68b5ba342b..f7d57a6d60213 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.styles.ts +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.styles.ts @@ -18,7 +18,9 @@ export const textBasedLanguagedEditorStyles = ( editorHeight: number, isCodeEditorExpanded: boolean, hasErrors: boolean, - isCodeEditorExpandedFocused: boolean + hasWarning: boolean, + isCodeEditorExpandedFocused: boolean, + hasReference: boolean ) => { let position = isCompactFocused ? ('absolute' as 'absolute') : ('relative' as 'relative'); // cast string to type 'relative' | 'absolute' if (isCodeEditorExpanded) { @@ -40,7 +42,7 @@ export const textBasedLanguagedEditorStyles = ( }, resizableContainer: { display: 'flex', - width: isCodeEditorExpanded ? '100%' : 'calc(100% - 80px)', + width: isCodeEditorExpanded ? '100%' : `calc(100% - ${hasReference ? 80 : 40}px)`, alignItems: isCompactFocused ? 'flex-start' : 'center', border: !isCompactFocused ? euiTheme.border.thin : 'none', borderTopLeftRadius: '6px', @@ -51,7 +53,7 @@ export const textBasedLanguagedEditorStyles = ( linesBadge: { position: 'absolute' as 'absolute', // cast string to type 'absolute', zIndex: 1, - right: hasErrors ? '60px' : '12px', + right: hasErrors || hasWarning ? '60px' : '12px', top: '50%', transform: 'translate(0, -50%)', }, diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.test.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.test.tsx index 90c973a609874..4e3853970d7a2 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.test.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.test.tsx @@ -16,6 +16,22 @@ import { TextBasedLanguagesEditor, TextBasedLanguagesEditorProps, } from './text_based_languages_editor'; +import { ReactWrapper } from 'enzyme'; + +jest.mock('./helpers', () => { + const module = jest.requireActual('./helpers'); + return { + ...module, + getDocumentationSections: () => ({ + groups: [ + { + label: 'How it works', + items: [], + }, + ], + }), + }; +}); import { of } from 'rxjs'; describe('TextBasedLanguagesEditor', () => { @@ -45,7 +61,7 @@ describe('TextBasedLanguagesEditor', () => { let props: TextBasedLanguagesEditorProps; beforeEach(() => { props = { - query: { sql: 'SELECT * FROM test' }, + query: { esql: 'from test' }, isCodeEditorExpanded: false, onTextLangQueryChange: jest.fn(), onTextLangQuerySubmit: jest.fn(), @@ -108,16 +124,32 @@ describe('TextBasedLanguagesEditor', () => { }); }); - it('should render the correct buttons for the inline code editor mode', async () => { + it('should render the warnings badge for the inline mode by default if warning are provides', async () => { + const newProps = { + ...props, + warning: 'Line 1: 20: Warning', + }; await act(async () => { - const component = mount(renderTextBasedLanguagesEditorComponent({ ...props })); - expect(component.find('[data-test-subj="TextBasedLangEditor-expand"]').length).not.toBe(0); + const component = mount(renderTextBasedLanguagesEditorComponent({ ...newProps })); expect( - component.find('[data-test-subj="TextBasedLangEditor-inline-documentation"]').length + component.find('[data-test-subj="TextBasedLangEditor-inline-warning-badge"]').length ).not.toBe(0); }); }); + it('should render the correct buttons for the inline code editor mode', async () => { + let component: ReactWrapper; + + await act(async () => { + component = mount(renderTextBasedLanguagesEditorComponent({ ...props })); + }); + component!.update(); + expect(component!.find('[data-test-subj="TextBasedLangEditor-expand"]').length).not.toBe(0); + expect( + component!.find('[data-test-subj="TextBasedLangEditor-inline-documentation"]').length + ).not.toBe(0); + }); + it('should call the expand editor function when expand button is clicked', async () => { const expandCodeEditorSpy = jest.fn(); const newProps = { @@ -136,12 +168,36 @@ describe('TextBasedLanguagesEditor', () => { ...props, isCodeEditorExpanded: true, }; + let component: ReactWrapper; + await act(async () => { + component = mount(renderTextBasedLanguagesEditorComponent({ ...newProps })); + }); + component!.update(); + expect( + component!.find('[data-test-subj="TextBasedLangEditor-toggleWordWrap"]').length + ).not.toBe(0); + expect(component!.find('[data-test-subj="TextBasedLangEditor-minimize"]').length).not.toBe(0); + expect(component!.find('[data-test-subj="TextBasedLangEditor-documentation"]').length).not.toBe( + 0 + ); + }); + + it('should not render the minimize button for the expanded code editor mode if the prop is set to true', async () => { + const newProps = { + ...props, + isCodeEditorExpanded: true, + hideMinimizeButton: true, + }; + let component: ReactWrapper; + await act(async () => { + component = mount(renderTextBasedLanguagesEditorComponent({ ...newProps })); + }); + component!.update(); await act(async () => { - const component = mount(renderTextBasedLanguagesEditorComponent({ ...newProps })); expect( component.find('[data-test-subj="TextBasedLangEditor-toggleWordWrap"]').length ).not.toBe(0); - expect(component.find('[data-test-subj="TextBasedLangEditor-minimize"]').length).not.toBe(0); + expect(component.find('[data-test-subj="TextBasedLangEditor-minimize"]').length).toBe(0); expect( component.find('[data-test-subj="TextBasedLangEditor-documentation"]').length ).not.toBe(0); diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index 5f432c090eb8c..5eb83f625493a 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -6,16 +6,27 @@ * Side Public License, v 1. */ -import React, { useRef, useEffect, useState, useCallback, memo } from 'react'; +import React, { useRef, memo, useEffect, useState, useCallback } from 'react'; import classNames from 'classnames'; -import { SQLLang, monaco } from '@kbn/monaco'; +import { + SQLLang, + monaco, + ESQL_LANG_ID, + ESQL_THEME_ID, + ESQLLang, + ESQLCustomAutocompleteCallbacks, +} from '@kbn/monaco'; import type { AggregateQuery } from '@kbn/es-query'; -import { getAggregateQueryMode } from '@kbn/es-query'; +import { getAggregateQueryMode, getLanguageDisplayName } from '@kbn/es-query'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; +import type { IndexManagementPluginSetup } from '@kbn/index-management-plugin/public'; +import type { SerializedEnrichPolicy } from '@kbn/index-management-plugin/common'; import { type LanguageDocumentationSections, LanguageDocumentationPopover, } from '@kbn/language-documentation-popover'; - +import { useKibana } from '@kbn/kibana-react-plugin/public'; import { i18n } from '@kbn/i18n'; import { EuiBadge, @@ -40,12 +51,14 @@ import { import { useDebounceWithOptions, parseErrors, + parseWarning, getInlineEditorText, getDocumentationSections, MonacoError, } from './helpers'; import { EditorFooter } from './editor_footer'; import { ResizableButton } from './resizable_button'; +import { fetchFieldsFromESQL } from './fetch_fields_from_esql'; import './overwrite.scss'; @@ -57,9 +70,17 @@ export interface TextBasedLanguagesEditorProps { isCodeEditorExpanded: boolean; detectTimestamp?: boolean; errors?: Error[]; + warning?: string; isDisabled?: boolean; isDarkMode?: boolean; dataTestSubj?: string; + hideMinimizeButton?: boolean; +} + +interface TextBasedEditorDeps { + dataViews: DataViewsPublicPluginStart; + expressions: ExpressionsStart; + indexManagementApiService?: IndexManagementPluginSetup['apiService']; } const MAX_COMPACT_VIEW_LENGTH = 250; @@ -72,6 +93,9 @@ const KEYCODE_ARROW_DOWN = 40; const languageId = (language: string) => { switch (language) { + case 'esql': { + return ESQL_LANG_ID; + } case 'sql': default: { return SQLLang.ID; @@ -82,6 +106,8 @@ const languageId = (language: string) => { let clickedOutside = false; let initialRender = true; let updateLinesFromModel = false; +let currentCursorContent = ''; + export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ query, onTextLangQueryChange, @@ -90,13 +116,17 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ isCodeEditorExpanded, detectTimestamp = false, errors, + warning, isDisabled, isDarkMode, + hideMinimizeButton, dataTestSubj, }: TextBasedLanguagesEditorProps) { const { euiTheme } = useEuiTheme(); const language = getAggregateQueryMode(query); const queryString: string = query[language] ?? ''; + const kibana = useKibana(); + const { dataViews, expressions, indexManagementApiService } = kibana.services; const [lines, setLines] = useState(1); const [code, setCode] = useState(queryString ?? ''); const [codeOneLiner, setCodeOneLiner] = useState(''); @@ -108,16 +138,21 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const [isCodeEditorExpandedFocused, setIsCodeEditorExpandedFocused] = useState(false); const [isWordWrapped, setIsWordWrapped] = useState(true); const [editorErrors, setEditorErrors] = useState([]); + const [editorWarning, setEditorWarning] = useState([]); + const [documentationSections, setDocumentationSections] = useState(); + const policiesRef = useRef([]); const styles = textBasedLanguagedEditorStyles( euiTheme, isCompactFocused, editorHeight, isCodeEditorExpanded, Boolean(errors?.length), - isCodeEditorExpandedFocused + Boolean(warning), + isCodeEditorExpandedFocused, + Boolean(documentationSections) ); const isDark = isDarkMode; const editorModel = useRef(); @@ -209,6 +244,18 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ if (updateLinesFromModel) { setLines(editorModel.current?.getLineCount() || 1); } + if (editor1?.current) { + const currentPosition = editor1.current?.getPosition(); + const content = editorModel.current?.getValueInRange({ + startLineNumber: 0, + startColumn: 0, + endLineNumber: currentPosition?.lineNumber ?? 1, + endColumn: currentPosition?.column ?? 1, + }); + if (content) { + currentCursorContent = content || editor1.current?.getValue(); + } + } }); editor1.current?.onDidFocusEditorText(() => { setIsCompactFocused(true); @@ -227,6 +274,12 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ if (!isCodeEditorExpanded) { editor1.current?.onDidContentSizeChange(updateHeight); } + if (warning && (!errors || !errors.length)) { + const parsedWarning = parseWarning(warning); + setEditorWarning(parsedWarning); + } else { + setEditorWarning([]); + } if (errors && errors.length) { const parsedErrors = parseErrors(errors, code); setEditorErrors(parsedErrors); @@ -238,7 +291,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ }, { skipFirstRender: false }, 256, - [errors] + [errors, warning] ); const onErrorClick = useCallback(({ startLineNumber, startColumn }: MonacoError) => { @@ -275,7 +328,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const text = getInlineEditorText(queryString, Boolean(hasLines)); const queryLength = text.length; const unusedSpace = - errors && errors.length + (errors && errors.length) || warning ? EDITOR_ONE_LINER_UNUSED_SPACE_WITH_ERRORS : EDITOR_ONE_LINER_UNUSED_SPACE; const charactersAlowed = Math.floor((width - unusedSpace) / FONT_WIDTH); @@ -288,7 +341,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ } } }, - [queryString, errors, isCompactFocused] + [isCompactFocused, queryString, errors, warning] ); useEffect(() => { @@ -329,6 +382,78 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ } }, [language, documentationSections]); + const getSourceIdentifiers: ESQLCustomAutocompleteCallbacks['getSourceIdentifiers'] = + useCallback(async () => { + const indices = await dataViews.getIndices({ + showAllIndices: false, + pattern: '*', + isRollupIndex: () => false, + }); + return indices.map((i) => i.name); + }, [dataViews]); + + const getFieldsIdentifiers: ESQLCustomAutocompleteCallbacks['getFieldsIdentifiers'] = useCallback( + async (ctx) => { + const pipes = currentCursorContent?.split('|'); + pipes?.pop(); + const validContent = pipes?.join('|'); + if (validContent) { + // ES|QL with limit 0 returns only the columns and is more performant + const esqlQuery = { + esql: `${validContent} | limit 0`, + }; + try { + const table = await fetchFieldsFromESQL(esqlQuery, expressions); + return table?.columns.map((c) => c.name) || []; + } catch (e) { + // no action yet + } + } + return []; + }, + [expressions] + ); + + const getPoliciesIdentifiers: ESQLCustomAutocompleteCallbacks['getPoliciesIdentifiers'] = + useCallback( + async (ctx) => { + const { data: policies, error } = + (await indexManagementApiService?.getAllEnrichPolicies()) || {}; + policiesRef.current = policies || []; + if (error || !policies) { + return []; + } + return policies.map(({ name, sourceIndices }) => ({ name, indices: sourceIndices })); + }, + [indexManagementApiService] + ); + + const getPolicyFieldsIdentifiers: ESQLCustomAutocompleteCallbacks['getPolicyFieldsIdentifiers'] = + useCallback( + async (ctx) => + policiesRef.current + .filter(({ name }) => ctx.userDefinedVariables.policyIdentifiers.includes(name)) + .flatMap(({ enrichFields }) => enrichFields), + [] + ); + + const getPolicyMatchingFieldIdentifiers: ESQLCustomAutocompleteCallbacks['getPolicyMatchingFieldIdentifiers'] = + useCallback( + async (ctx) => { + // try to load the list if none is present yet but + // at least one policy is declared in the userDefinedVariables + // (this happens if the user pastes an ESQL statement with the policy name in it) + if (!policiesRef.current.length && ctx.userDefinedVariables.policyIdentifiers.length) { + await getPoliciesIdentifiers(ctx); + } + const matchingField = policiesRef.current.find(({ name }) => + ctx.userDefinedVariables.policyIdentifiers.includes(name) + )?.matchField; + return matchingField ? [matchingField] : []; + }, + [getPoliciesIdentifiers] + ); + const codeEditorOptions: CodeEditorProps['options'] = { automaticLayout: false, accessibilitySupport: 'off', @@ -343,7 +468,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ minimap: { enabled: false }, wordWrap: isWordWrapped ? 'on' : 'off', lineNumbers: showLineNumbers ? 'on' : 'off', - theme: isDark ? 'vs-dark' : 'vs', + theme: language === 'esql' ? ESQL_THEME_ID : isDark ? 'vs-dark' : 'vs', lineDecorationsWidth: 12, autoIndent: 'none', wrappingIndent: 'none', @@ -355,7 +480,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ vertical: 'auto', }, overviewRulerBorder: false, - readOnly: isDisabled, + readOnly: + isDisabled || Boolean(!isCompactFocused && codeOneLiner && codeOneLiner.includes('...')), }; if (isCompactFocused) { @@ -423,48 +549,54 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ - - - + { - expandCodeEditor(false); - updateLinesFromModel = false; - }} - /> - - + > + { + expandCodeEditor(false); + updateLinesFromModel = false; + }} + /> + + + )} - + {documentationSections && ( + + + + )}
    @@ -515,11 +647,33 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ {errors.length} )} + {!isCompactFocused && warning && (!errors || errors.length === 0) && ( + + {editorWarning.length} + + )} { editor1.current = editor; @@ -537,6 +691,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ lines={lines} containerCSS={styles.bottomContainer} errors={editorErrors} + warning={editorWarning} onErrorClick={onErrorClick} refreshErrors={onTextLangQuerySubmit} detectTimestamp={detectTimestamp} @@ -569,7 +724,14 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ onClick={() => expandCodeEditor(true)} data-test-subj="TextBasedLangEditor-expand" css={{ - borderRadius: 0, + ...(documentationSections + ? { + borderRadius: 0, + } + : { + borderTopLeftRadius: 0, + borderBottomLeftRadius: 0, + }), backgroundColor: isDark ? euiTheme.colors.lightestShade : '#e9edf3', border: '1px solid rgb(17 43 134 / 10%) !important', }} @@ -577,28 +739,34 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({
    - + + sections={documentationSections} + buttonProps={{ + display: 'empty', + 'data-test-subj': 'TextBasedLangEditor-inline-documentation', + 'aria-label': i18n.translate( + 'textBasedEditor.query.textBasedLanguagesEditor.documentationLabel', + { + defaultMessage: 'Documentation', + } + ), + size: 'm', + css: { + borderTopLeftRadius: 0, + borderBottomLeftRadius: 0, + backgroundColor: isDark ? euiTheme.colors.lightestShade : '#e9edf3', + border: '1px solid rgb(17 43 134 / 10%) !important', + borderLeft: 'transparent !important', + }, + }} + /> + + )}
    @@ -609,6 +777,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ lines={lines} containerCSS={styles.bottomContainer} errors={editorErrors} + warning={editorWarning} onErrorClick={onErrorClick} refreshErrors={onTextLangQuerySubmit} detectTimestamp={detectTimestamp} diff --git a/packages/kbn-text-based-editor/tsconfig.json b/packages/kbn-text-based-editor/tsconfig.json index cefbe0335575b..63222d0d6026b 100644 --- a/packages/kbn-text-based-editor/tsconfig.json +++ b/packages/kbn-text-based-editor/tsconfig.json @@ -19,7 +19,11 @@ "@kbn/core", "@kbn/kibana-react-plugin", "@kbn/language-documentation-popover", - "@kbn/test-jest-helpers" + "@kbn/test-jest-helpers", + "@kbn/data-plugin", + "@kbn/expressions-plugin", + "@kbn/data-views-plugin", + "@kbn/index-management-plugin" ], "exclude": [ "target/**/*", diff --git a/packages/kbn-unified-data-table/README.md b/packages/kbn-unified-data-table/README.md new file mode 100644 index 0000000000000..576a676289d7a --- /dev/null +++ b/packages/kbn-unified-data-table/README.md @@ -0,0 +1,241 @@ +# @kbn/unified-data-table + +This package contains components and services for the unified data table UI (as used in Discover). + +## UnifiedDataTable Component +Props description: +| Property | Type | Description | +| :--- | :--- | :--- | +| **ariaLabelledBy** | string | Determines which element labels the grid for ARIA. | +| **className** | (optional) string | Optional class name to apply. | +| **columns** | string[] | Determines ids of the columns which are displayed. | +| **expandedDoc** | (optional) DataTableRecord | If set, the given document is displayed in a flyout. | +| **dataView** | DataView | The used data view. | +| **loadingState** | DataLoadingState | Determines if data is currently loaded. | +| **onFilter** | DocViewFilterFn | Function to add a filter in the grid cell or document flyout. | +| **onResize** | (optional)(colSettings: { columnId: string; width: number }) => void; | Function triggered when a column is resized by the user. | +| **onSetColumns** | (columns: string[], hideTimeColumn: boolean) => void; | Function to set all columns. | +| **onSort** | (optional)(sort: string[][]) => void; | Function to change sorting of the documents, skipped when isSortEnabled is set to false. | +| **rows** | (optional)DataTableRecord[] | Array of documents provided by Elasticsearch. | +| **sampleSize** | number | The max size of the documents returned by Elasticsearch. | +| **setExpandedDoc** | (optional)(doc?: DataTableRecord) => void; | Function to set the expanded document, which is displayed in a flyout. | +| **settings** | (optional)UnifiedDataTableSettings | Grid display settings persisted in Elasticsearch (e.g. column width). | +| **searchDescription** | (optional)string | Search description. | +| **searchTitle** | (optional)string | Search title. | +| **showTimeCol** | boolean | Determines whether the time columns should be displayed (legacy settings). | +| **showFullScreenButton** | (optional)boolean | Determines whether the full screen button should be displayed. | +| **isSortEnabled** | (optional)boolean | Manage user sorting control. | +| **sort** | SortOrder[] | Current sort setting. | +| **useNewFieldsApi** | boolean | How the data is fetched. | +| **isPaginationEnabled** | (optional)boolean | Manage pagination control. | +| **controlColumnIds** | (optional)string[] | List of used control columns (available: 'openDetails', 'select'). | +| **rowHeightState** | (optional)number | Row height from state. | +| **onUpdateRowHeight** | (optional)(rowHeight: number) => void; | Update row height state. | +| **isPlainRecord** | (optional)boolean | Is text base lang mode enabled. | +| **rowsPerPageState** | (optional)number | Current state value for rowsPerPage. | +| **onUpdateRowsPerPage** | (optional)(rowsPerPage: number) => void; | Update rows per page state. | +| **onFieldEdited** | (optional)() => void; | Callback to execute on edit runtime field. | +| **cellActionsTriggerId** | (optional)string | Optional triggerId to retrieve the column cell actions that will override the default ones. | +| **services** | See Required **services** list below | Service dependencies. | +| **renderDocumentView** | (optional)(hit: DataTableRecord,displayedRows: DataTableRecord[],displayedColumns: string[]) => JSX.Element | undefined; | Callback to render DocumentView when the document is expanded. | +| **configRowHeight** | (optional)number | Optional value for providing configuration setting for UnifiedDataTable rows height. | +| **showMultiFields** | (optional)boolean | Optional value for providing configuration setting for enabling to display the complex fields in the table. Default is true. | +| **maxDocFieldsDisplayed** | (optional)number | Optional value for providing configuration setting for maximum number of document fields to display in the table. Default is 50. | +| **externalControlColumns** | (optional)EuiDataGridControlColumn[] | Optional value for providing EuiDataGridControlColumn list of the additional leading control columns. UnifiedDataTable includes two control columns: Open Details and Select. | +| **totalHits** | (optional)number | Number total hits from ES. | +| **onFetchMoreRecords** | (optional)() => void | To fetch more. | +| **externalAdditionalControls** | (optional)React.ReactNode | Optional value for providing the additional controls available in the UnifiedDataTable toolbar to manage it's records or state. UnifiedDataTable includes Columns, Sorting and Bulk Actions. | +| **rowsPerPageOptions** | (optional)number[] | Optional list of number type values to set custom UnifiedDataTable paging options to display the records per page. | +| **renderCustomGridBody** | (optional)(args: EuiDataGridCustomBodyProps) => React.ReactNode; | An optional function called to completely customize and control the rendering of EuiDataGrid's body and cell placement. | +| **trailingControlColumns** | (optional)EuiDataGridControlColumn[] | An optional list of the EuiDataGridControlColumn type for setting trailing control columns standard for EuiDataGrid. | +| **visibleCellActions** | (optional)number | An optional value for a custom number of the visible cell actions in the table. By default is up to 3. | +| **externalCustomRenderers** | (optional)Record React.ReactNode>; | An optional settings for a specified fields rendering like links. Applied only for the listed fields rendering. | +| **consumer** | (optional)string | Name of the UnifiedDataTable consumer component or application. | +| **componentsTourSteps** | (optional)Record | Optional key/value pairs to set guided onboarding steps ids for a data table components included to guided tour. | + +*Required **services** list: +``` + theme: ThemeServiceStart; + fieldFormats: FieldFormatsStart; + uiSettings: IUiSettingsClient; + dataViewFieldEditor: DataViewFieldEditorStart; + toastNotifications: ToastsStart; + storage: Storage; + data: DataPublicPluginStart; +``` + +Usage example: + +``` + // Memoize unified data table to avoid the unnecessary re-renderings + const DataTableMemoized = React.memo(UnifiedDataTable); + + // Add memoized component with all needed props + { + // Add logic to refetch the data when the filter by field was added/removed. Refetch data. + }} + onResize={(colSettings: { columnId: string; width: number }) => { + // Update the table state with the new width for the column + }} + onSetColumns={(columns: string[], hideTimeColumn: boolean) => { + // Update table state with the new columns. Refetch data. + }} + onSort={!isTextBasedQuery ? onSort : undefined + // Update table state with the new sorting settings. Refetch data. + } + rows={searchResultRows} + sampleSize={500} + setExpandedDoc={() => { + // Callback function to do the logic when the document is expanded + }} + settings={tableSettings} + showTimeCol={true} + isSortEnabled={true} + sort={sortingColumns} + rowHeightState={3} + onUpdateRowHeight={(rowHeight: number) => { + // Do the state update with the new setting of the row height + }} + isPlainRecord={isTextBasedQuery} + rowsPerPageState={50} + onUpdateRowsPerPage={(rowHeight: number) => { + // Do the state update with the new number of the rows per page + } + onFieldEdited={() => + // Callback to execute on edit runtime field. Refetch data. + } + cellActionsTriggerId={SecurityCellActionsTrigger.DEFAULT} + services={{ + theme, + fieldFormats, + storage, + toastNotifications: toastsService, + uiSettings, + dataViewFieldEditor, + data: dataPluginContract, + }} + visibleCellActions={3} + externalCustomRenderers={{ + // Set the record style definition for the specific fields rendering Record React.ReactNode> + }} + renderDocumentView={() => + // Implement similar callback to render the Document flyout + const renderDetailsPanel = useCallback( + () => ( + + ), + [browserFields, handleOnPanelClosed, runtimeMappings, timelineId] + ); + } + externalControlColumns={leadingControlColumns} + externalAdditionalControls={additionalControls} + trailingControlColumns={trailingControlColumns} + renderCustomGridBody={renderCustomGridBody} + rowsPerPageOptions={[10, 30, 40, 100]} + showFullScreenButton={false} + useNewFieldsApi={true} + maxDocFieldsDisplayed={50} + consumer="timeline" + totalHits={ + // total number of the documents in the search query result. For example: 1200 + } + onFetchMoreRecords={() => { + // Do some data fetch to get more data + }} + configRowHeight={3} + showMultiFields={true} + componentsTourSteps={'expandButton': DISCOVER_TOUR_STEP_ANCHOR_IDS.expandDocument} + /> +``` + +## JsonCodeEditorCommon Component +Props description: +| Property | Type | Description | +| :--- | :--- | :--- | +| **width** | (optional) string or number | Editor component width. | +| **height** | (optional) string or number | Editor component height. | +| **hasLineNumbers** | (optional) boolean | Define if the editor component has line numbers style. | +| **hideCopyButton** | (optional) boolean | Show/hide setting for Copy button. | +| **onEditorDidMount** | (editor: monaco.editor.IStandaloneCodeEditor) => void | Do some logic to update the state with the edotor component value. | + +Usage example: + +``` + setEditor(editorNode)} +/> + +``` + +## Utils + +* `getRowsPerPageOptions(currentRowsPerPage)` - gets list of the table defaults for perPage options. + +* `getDisplayedColumns(currentRowsPerPage)` - gets list of the table columns with the logic to define the empty list with _source column. + +* `popularizeField(...)` - helper function to define the dataView persistance and save indexPattern update capabilities. + +## Hooks + +* `useColumns(...)` - this hook define the state update for the columns event handlers and allows to use them for external components outside the UnifiedDataTable. + +An example of using hooks for defining event handlers for columns management with setting the consumer specific setAppState: + +``` +const { + columns: currentColumns, + onAddColumn, + onRemoveColumn, + onMoveColumn, + onSetColumns, + } = useColumns({ + capabilities, + defaultOrder: uiSettings.get(SORT_DEFAULT_ORDER_SETTING), + dataView, + dataViews, + setAppState: stateContainer.appState.update, + useNewFieldsApi, + columns, + sort, + }); + +// Use onAddColumn, onRemoveColumn handlers in the DocumentView + +const renderDocumentView = useCallback( + (hit: DataTableRecord, displayedRows: DataTableRecord[], displayedColumns: string[]) => ( + setExpandedDoc(undefined)} + setExpandedDoc={setExpandedDoc} + query={query} + /> + ), + [dataView, onAddColumn, onAddFilter, onRemoveColumn, query, savedSearch.id, setExpandedDoc] + ); +``` \ No newline at end of file diff --git a/packages/kbn-unified-data-table/__mocks__/config.ts b/packages/kbn-unified-data-table/__mocks__/config.ts new file mode 100644 index 0000000000000..b8ae4a531038c --- /dev/null +++ b/packages/kbn-unified-data-table/__mocks__/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 and the Server Side Public License, v 1; you may 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 { Config } from '@kbn/config'; + +export type ConfigMock = jest.Mocked; + +const createConfigMock = (): ConfigMock => ({ + has: jest.fn(), + get: jest.fn(), + set: jest.fn(), + getFlattenedPaths: jest.fn(), + toRaw: jest.fn(), +}); + +export const configMock = { + create: createConfigMock, +}; diff --git a/packages/kbn-unified-data-table/__mocks__/data_view_complex.ts b/packages/kbn-unified-data-table/__mocks__/data_view_complex.ts new file mode 100644 index 0000000000000..8122103c9f4d7 --- /dev/null +++ b/packages/kbn-unified-data-table/__mocks__/data_view_complex.ts @@ -0,0 +1,419 @@ +/* + * Copyright 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 { DataView } from '@kbn/data-views-plugin/public'; +import { buildDataViewMock } from '@kbn/discover-utils/src/__mocks__'; + +const fields = [ + { + count: 0, + name: '_id', + type: 'string', + esTypes: ['_id'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: '_index', + type: 'string', + esTypes: ['_index'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + count: 0, + name: '_score', + type: 'number', + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: '_source', + type: '_source', + esTypes: ['_source'], + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: '_type', + type: 'string', + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 2, + name: 'array_objects.description', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'array_objects.description.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'array_objects.description', + }, + }, + }, + { + count: 0, + name: 'array_objects.name', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'array_objects.name.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'array_objects.name', + }, + }, + }, + { + count: 0, + name: 'array_tags', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'array_tags.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'array_tags', + }, + }, + }, + { + count: 0, + name: 'binary_blob', + type: 'unknown', + esTypes: ['binary'], + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'bool_enabled', + type: 'boolean', + esTypes: ['boolean'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'date', + type: 'date', + esTypes: ['date'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 1, + name: 'date_nanos', + type: 'date', + esTypes: ['date_nanos'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'flattened_labels', + type: 'unknown', + esTypes: ['flattened'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'geo_point', + type: 'geo_point', + esTypes: ['geo_point'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 1, + name: 'geometry', + type: 'unknown', + esTypes: ['shape'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 1, + name: 'histogram', + type: 'histogram', + esTypes: ['histogram'], + scripted: false, + searchable: false, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'ip_addr', + type: 'ip', + esTypes: ['ip'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 4, + name: 'keyword_key', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'nested_user.first', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + subType: { + nested: { + path: 'nested_user', + }, + }, + }, + { + count: 0, + name: 'nested_user.first.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'nested_user.first', + }, + nested: { + path: 'nested_user', + }, + }, + }, + { + count: 0, + name: 'nested_user.last', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + subType: { + nested: { + path: 'nested_user', + }, + }, + }, + { + count: 0, + name: 'nested_user.last.keyword', + type: 'string', + esTypes: ['keyword'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + subType: { + multi: { + parent: 'nested_user.last', + }, + nested: { + path: 'nested_user', + }, + }, + }, + { + count: 3, + name: 'number_amount', + type: 'number', + esTypes: ['long'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 3, + name: 'number_price', + type: 'number', + esTypes: ['float'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 0, + name: 'object_user.first', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'object_user.last', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'range_time_frame', + type: 'date_range', + esTypes: ['date_range'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 1, + name: 'rank_features', + type: 'unknown', + esTypes: ['rank_features'], + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 5, + name: 'text_message', + type: 'string', + esTypes: ['text'], + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'vector', + type: 'unknown', + esTypes: ['dense_vector'], + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + { + count: 0, + name: 'version', + type: 'string', + esTypes: ['version'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + { + count: 1, + script: 'return "hi there"', + lang: 'painless', + name: 'scripted_string', + type: 'string', + scripted: true, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, + { + count: 0, + name: 'runtime_number', + type: 'number', + esTypes: ['double'], + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }, +] as DataView['fields']; + +export const dataViewComplexMock = buildDataViewMock({ + name: 'data-view-with-various-field-types', + fields, + timeFieldName: 'data', +}); diff --git a/packages/kbn-unified-data-table/__mocks__/data_view_with_timefield.ts b/packages/kbn-unified-data-table/__mocks__/data_view_with_timefield.ts new file mode 100644 index 0000000000000..374b6b23f837b --- /dev/null +++ b/packages/kbn-unified-data-table/__mocks__/data_view_with_timefield.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 { DataView } from '@kbn/data-views-plugin/public'; +import { buildDataViewMock } from '@kbn/discover-utils/src/__mocks__'; + +const fields = [ + { + name: '_index', + type: 'string', + scripted: false, + filterable: true, + }, + { + name: 'timestamp', + displayName: 'timestamp', + type: 'date', + scripted: false, + filterable: true, + aggregatable: true, + sortable: true, + }, + { + name: 'message', + displayName: 'message', + type: 'string', + scripted: false, + filterable: false, + }, + { + name: 'extension', + displayName: 'extension', + type: 'string', + scripted: false, + filterable: true, + aggregatable: true, + }, + { + name: 'bytes', + displayName: 'bytes', + type: 'number', + scripted: false, + filterable: true, + aggregatable: true, + }, + { + name: 'scripted', + displayName: 'scripted', + type: 'number', + scripted: true, + filterable: false, + }, +] as DataView['fields']; + +export const dataViewWithTimefieldMock = buildDataViewMock({ + name: 'index-pattern-with-timefield', + fields, + timeFieldName: 'timestamp', +}); diff --git a/packages/kbn-unified-data-table/__mocks__/data_views.ts b/packages/kbn-unified-data-table/__mocks__/data_views.ts new file mode 100644 index 0000000000000..bdbf63ecfbfbe --- /dev/null +++ b/packages/kbn-unified-data-table/__mocks__/data_views.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { DataViewsContract } from '@kbn/data-views-plugin/public'; +import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; +import { dataViewComplexMock } from './data_view_complex'; +import { dataViewWithTimefieldMock } from './data_view_with_timefield'; + +export const dataViewMockList = [dataViewMock, dataViewComplexMock, dataViewWithTimefieldMock]; + +export function createDataViewsMock() { + return { + getCache: async () => { + return [dataViewMock]; + }, + get: async (id: string) => { + if (id === 'invalid-data-view-id') { + return Promise.reject('Invalid'); + } + const dataView = dataViewMockList.find((dv) => dv.id === id); + if (dataView) { + return Promise.resolve(dataView); + } else { + return Promise.reject(`DataView ${id} not found`); + } + }, + getDefaultDataView: jest.fn(() => dataViewMock), + updateSavedObject: jest.fn(), + getIdsWithTitle: jest.fn(() => { + return Promise.resolve(dataViewMockList); + }), + createFilter: jest.fn(), + create: jest.fn(), + clearInstanceCache: jest.fn(), + getFieldsForIndexPattern: jest.fn((dataView) => dataView.fields), + refreshFields: jest.fn(), + } as unknown as jest.Mocked; +} + +export const dataViewsMock = createDataViewsMock(); diff --git a/src/plugins/discover/public/__mocks__/es_hits_complex.ts b/packages/kbn-unified-data-table/__mocks__/es_hits_complex.ts similarity index 100% rename from src/plugins/discover/public/__mocks__/es_hits_complex.ts rename to packages/kbn-unified-data-table/__mocks__/es_hits_complex.ts diff --git a/packages/kbn-unified-data-table/__mocks__/external_control_columns.tsx b/packages/kbn-unified-data-table/__mocks__/external_control_columns.tsx new file mode 100644 index 0000000000000..d67afccc01559 --- /dev/null +++ b/packages/kbn-unified-data-table/__mocks__/external_control_columns.tsx @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useState } from 'react'; +import { + EuiCheckbox, + EuiButtonIcon, + EuiPopover, + EuiFlexGroup, + EuiFlexItem, + EuiPopoverTitle, + EuiSpacer, + EuiDataGridControlColumn, +} from '@elastic/eui'; + +const SelectionHeaderCell = () => { + return ( +
    + null} /> +
    + ); +}; + +const SimpleHeaderCell = () => { + return ( +
    + {'Additional Actions'} +
    + ); +}; + +const SelectionRowCell = ({ rowIndex }: { rowIndex: number }) => { + return ( +
    + null} + /> +
    + ); +}; + +const TestTrailingColumn = () => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + return ( + setIsPopoverOpen(!isPopoverOpen)} + /> + } + data-test-subj="test-trailing-column-popover-button" + closePopover={() => setIsPopoverOpen(false)} + > + {'Actions'} +
    + + + +
    +
    + ); +}; + +export const testTrailingControlColumns = [ + { + id: 'actions', + width: 96, + headerCellRender: SimpleHeaderCell, + rowCellRender: TestTrailingColumn, + }, +]; + +export const testLeadingControlColumn: EuiDataGridControlColumn = { + id: 'test-leading-control', + headerCellRender: SelectionHeaderCell, + rowCellRender: SelectionRowCell, + width: 100, +}; diff --git a/packages/kbn-unified-data-table/__mocks__/local_storage_mock.ts b/packages/kbn-unified-data-table/__mocks__/local_storage_mock.ts new file mode 100644 index 0000000000000..42cd33d2eb699 --- /dev/null +++ b/packages/kbn-unified-data-table/__mocks__/local_storage_mock.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export class LocalStorageMock { + private store: Record; + constructor(defaultStore: Record) { + this.store = defaultStore; + } + clear() { + this.store = {}; + } + get(key: string) { + return this.store[key] || null; + } + set(key: string, value: unknown) { + this.store[key] = String(value); + } + remove(key: string) { + delete this.store[key]; + } +} diff --git a/packages/kbn-unified-data-table/__mocks__/services.ts b/packages/kbn-unified-data-table/__mocks__/services.ts new file mode 100644 index 0000000000000..2c74668644497 --- /dev/null +++ b/packages/kbn-unified-data-table/__mocks__/services.ts @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { of } from 'rxjs'; +import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; +import { expressionsPluginMock } from '@kbn/expressions-plugin/public/mocks'; +import { chromeServiceMock, coreMock } from '@kbn/core/public/mocks'; +import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; +import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; +import { IUiSettingsClient, ToastsStart } from '@kbn/core/public'; +import { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; + +export function createServicesMock() { + const expressionsPlugin = expressionsPluginMock.createStartContract(); + + expressionsPlugin.run = jest.fn(() => + of({ + partial: false, + result: { + rows: [], + }, + }) + ) as unknown as typeof expressionsPlugin.run; + + const corePluginMock = coreMock.createStart(); + + const uiSettingsMock: Partial = { + get: jest.fn(), + isDefault: jest.fn((key: string) => { + return true; + }), + }; + + corePluginMock.uiSettings = { + ...corePluginMock.uiSettings, + ...uiSettingsMock, + }; + + const theme = { + theme$: of({ darkMode: false }), + }; + + corePluginMock.theme = theme; + + const dataPlugin = dataPluginMock.createStartContract(); + + return { + core: corePluginMock, + charts: chartPluginMock.createSetupContract(), + chrome: chromeServiceMock.createStartContract(), + history: () => ({ + location: { + search: '', + }, + listen: jest.fn(), + }), + fieldFormats: fieldFormatsMock, + filterManager: jest.fn(), + inspector: { + open: jest.fn(), + }, + uiActions: uiActionsPluginMock.createStartContract(), + uiSettings: uiSettingsMock as IUiSettingsClient, + http: { + basePath: '/', + }, + dataViewEditor: { + openEditor: jest.fn(), + userPermissions: { + editDataView: jest.fn(() => true), + }, + }, + dataViewFieldEditor: { + openEditor: jest.fn(), + userPermissions: { + editIndexPattern: jest.fn(() => true), + }, + } as unknown as DataViewFieldEditorStart, + theme, + storage: { + clear: jest.fn(), + get: jest.fn(), + set: jest.fn(), + remove: jest.fn(), + }, + toastNotifications: { + addInfo: jest.fn(), + addWarning: jest.fn(), + addDanger: jest.fn(), + addSuccess: jest.fn(), + } as unknown as ToastsStart, + expressions: expressionsPlugin, + savedObjectsTagging: { + ui: { + getTagIdsFromReferences: jest.fn().mockResolvedValue([]), + updateTagsReferences: jest.fn(), + }, + }, + dataViews: jest.fn(), + locator: { + useUrl: jest.fn(() => ''), + navigate: jest.fn(), + getUrl: jest.fn(() => Promise.resolve('')), + }, + contextLocator: { getRedirectUrl: jest.fn(() => '') }, + singleDocLocator: { getRedirectUrl: jest.fn(() => '') }, + data: dataPlugin, + }; +} + +export const servicesMock = createServicesMock(); diff --git a/src/plugins/discover/public/__mocks__/grid_context.ts b/packages/kbn-unified-data-table/__mocks__/table_context.ts similarity index 69% rename from src/plugins/discover/public/__mocks__/grid_context.ts rename to packages/kbn-unified-data-table/__mocks__/table_context.ts index 8949945c2b0d8..4a4a75b0fa9e5 100644 --- a/src/plugins/discover/public/__mocks__/grid_context.ts +++ b/packages/kbn-unified-data-table/__mocks__/table_context.ts @@ -10,13 +10,13 @@ import type { DataView } from '@kbn/data-views-plugin/public'; import { dataViewMock, esHitsMock } from '@kbn/discover-utils/src/__mocks__'; import { dataViewComplexMock } from './data_view_complex'; import { esHitsComplex } from './es_hits_complex'; -import { discoverServiceMock } from './services'; -import { GridContext } from '../components/discover_grid/discover_grid_context'; -import { convertValueToString } from '../utils/convert_value_to_string'; +import { servicesMock } from './services'; +import { DataTableContext } from '../src/table_context'; +import { convertValueToString } from '../src/utils/convert_value_to_string'; import { buildDataTableRecord } from '@kbn/discover-utils'; import type { EsHitRecord } from '@kbn/discover-utils/types'; -const buildGridContext = (dataView: DataView, rows: EsHitRecord[]): GridContext => { +const buildTableContext = (dataView: DataView, rows: EsHitRecord[]): DataTableContext => { const usedRows = rows.map((row) => { return buildDataTableRecord(row, dataView); }); @@ -34,7 +34,7 @@ const buildGridContext = (dataView: DataView, rows: EsHitRecord[]): GridContext convertValueToString({ rowIndex, columnId, - fieldFormats: discoverServiceMock.fieldFormats, + fieldFormats: servicesMock.fieldFormats, rows: usedRows, dataView, options, @@ -42,6 +42,6 @@ const buildGridContext = (dataView: DataView, rows: EsHitRecord[]): GridContext }; }; -export const discoverGridContextMock = buildGridContext(dataViewMock, esHitsMock); +export const dataTableContextMock = buildTableContext(dataViewMock, esHitsMock); -export const discoverGridContextComplexMock = buildGridContext(dataViewComplexMock, esHitsComplex); +export const dataTableContextComplexMock = buildTableContext(dataViewComplexMock, esHitsComplex); diff --git a/packages/kbn-unified-data-table/index.ts b/packages/kbn-unified-data-table/index.ts new file mode 100644 index 0000000000000..2c5e995619436 --- /dev/null +++ b/packages/kbn-unified-data-table/index.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. + */ + +export { UnifiedDataTable, DataLoadingState } from './src/components/data_table'; +export type { UnifiedDataTableProps } from './src/components/data_table'; +export { getDisplayedColumns } from './src/utils/columns'; + +export { JSONCodeEditorCommonMemoized } from './src/components/json_code_editor/json_code_editor_common'; + +export * from './src/types'; +export * as columnActions from './src/components/actions/columns'; + +export { getRowsPerPageOptions } from './src/utils/rows_per_page'; +export { popularizeField } from './src/utils/popularize_field'; + +export { useColumns } from './src/hooks/use_data_grid_columns'; diff --git a/packages/kbn-unified-data-table/jest.config.js b/packages/kbn-unified-data-table/jest.config.js new file mode 100644 index 0000000000000..5256221baacf4 --- /dev/null +++ b/packages/kbn-unified-data-table/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-unified-data-table'], +}; diff --git a/packages/kbn-unified-data-table/kibana.jsonc b/packages/kbn-unified-data-table/kibana.jsonc new file mode 100644 index 0000000000000..de49c4caff1e5 --- /dev/null +++ b/packages/kbn-unified-data-table/kibana.jsonc @@ -0,0 +1,6 @@ +{ + "type": "shared-common", + "id": "@kbn/unified-data-table", + "description": "Contains functionality for the unified data table which can be integrated into apps", + "owner": "@elastic/kibana-data-discovery" +} diff --git a/packages/kbn-unified-data-table/package.json b/packages/kbn-unified-data-table/package.json new file mode 100644 index 0000000000000..79d4157293c05 --- /dev/null +++ b/packages/kbn-unified-data-table/package.json @@ -0,0 +1,10 @@ +{ + "name": "@kbn/unified-data-table", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0", + "sideEffects": [ + "*.css", + "*.scss" + ] +} diff --git a/src/plugins/discover/public/components/doc_table/actions/columns.test.ts b/packages/kbn-unified-data-table/src/components/actions/columns.test.ts similarity index 90% rename from src/plugins/discover/public/components/doc_table/actions/columns.test.ts rename to packages/kbn-unified-data-table/src/components/actions/columns.test.ts index c95ff0d8d7252..d8480cf2067b4 100644 --- a/src/plugins/discover/public/components/doc_table/actions/columns.test.ts +++ b/packages/kbn-unified-data-table/src/components/actions/columns.test.ts @@ -7,15 +7,13 @@ */ import { getStateColumnActions } from './columns'; -import { configMock } from '../../../__mocks__/config'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { dataViewsMock } from '../../../__mocks__/data_views'; import { Capabilities } from '@kbn/core/types'; -import { DiscoverAppState } from '../../../application/main/services/discover_app_state_container'; +import { dataViewsMock } from '../../../__mocks__/data_views'; function getStateColumnAction( - state: DiscoverAppState, - setAppState: (state: Partial) => void + state: { columns?: string[]; sort?: string[][] }, + setAppState: (state: { columns: string[]; sort?: string[][] }) => void ) { return getStateColumnActions({ capabilities: { @@ -23,13 +21,13 @@ function getStateColumnAction( save: false, }, } as unknown as Capabilities, - config: configMock, dataView: dataViewMock, dataViews: dataViewsMock, useNewFieldsApi: true, setAppState, columns: state.columns, sort: state.sort, + defaultOrder: 'desc', }); } diff --git a/src/plugins/discover/public/components/doc_table/actions/columns.ts b/packages/kbn-unified-data-table/src/components/actions/columns.ts similarity index 83% rename from src/plugins/discover/public/components/doc_table/actions/columns.ts rename to packages/kbn-unified-data-table/src/components/actions/columns.ts index b45d95433165a..3355902ece86e 100644 --- a/src/plugins/discover/public/components/doc_table/actions/columns.ts +++ b/packages/kbn-unified-data-table/src/components/actions/columns.ts @@ -5,13 +5,10 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { Capabilities, IUiSettingsClient } from '@kbn/core/public'; -import { DataViewsContract } from '@kbn/data-plugin/public'; -import { DataView } from '@kbn/data-views-plugin/public'; -import { SORT_DEFAULT_ORDER_SETTING } from '@kbn/discover-utils'; -import { DiscoverAppStateContainer } from '../../../application/main/services/discover_app_state_container'; -import { GetStateReturn as ContextGetStateReturn } from '../../../application/context/services/context_state'; -import { popularizeField } from '../../../utils/popularize_field'; +import { Capabilities } from '@kbn/core/public'; +import type { DataViewsContract } from '@kbn/data-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import { popularizeField } from '../../utils/popularize_field'; /** * Helper function to provide a fallback to a single _source column if the given array of columns @@ -57,27 +54,26 @@ export function moveColumn(columns: string[], columnName: string, newIndex: numb export function getStateColumnActions({ capabilities, - config, dataView, dataViews, useNewFieldsApi, setAppState, columns, sort, + defaultOrder, }: { capabilities: Capabilities; - config: IUiSettingsClient; dataView: DataView; dataViews: DataViewsContract; useNewFieldsApi: boolean; - setAppState: DiscoverAppStateContainer['update'] | ContextGetStateReturn['setAppState']; + setAppState: (state: { columns: string[]; sort?: string[][] }) => void; columns?: string[]; sort: string[][] | undefined; + defaultOrder: string; }) { function onAddColumn(columnName: string) { popularizeField(dataView, columnName, dataViews, capabilities); const nextColumns = addColumn(columns || [], columnName, useNewFieldsApi); - const defaultOrder = config.get(SORT_DEFAULT_ORDER_SETTING); const nextSort = columnName === '_score' && !sort?.length ? [['_score', defaultOrder]] : sort; setAppState({ columns: nextColumns, sort: nextSort }); } diff --git a/src/plugins/discover/public/components/discover_grid/build_copy_column_button.test.tsx b/packages/kbn-unified-data-table/src/components/build_copy_column_button.test.tsx similarity index 86% rename from src/plugins/discover/public/components/discover_grid/build_copy_column_button.test.tsx rename to packages/kbn-unified-data-table/src/components/build_copy_column_button.test.tsx index dda3a904bda3f..02a3c6e7e425e 100644 --- a/src/plugins/discover/public/components/discover_grid/build_copy_column_button.test.tsx +++ b/packages/kbn-unified-data-table/src/components/build_copy_column_button.test.tsx @@ -9,8 +9,8 @@ import React from 'react'; import { EuiButton } from '@elastic/eui'; import { mountWithIntl } from '@kbn/test-jest-helpers'; -import { discoverServiceMock } from '../../__mocks__/services'; -import { discoverGridContextMock } from '../../__mocks__/grid_context'; +import { servicesMock } from '../../__mocks__/services'; +import { dataTableContextMock } from '../../__mocks__/table_context'; import { buildCopyColumnNameButton, buildCopyColumnValuesButton } from './build_copy_column_button'; const execCommandMock = (global.document.execCommand = jest.fn()); @@ -20,7 +20,7 @@ describe('Build a column button to copy to clipboard', () => { it('should copy a column name to clipboard on click', () => { const { label, iconType, onClick } = buildCopyColumnNameButton({ columnDisplayName: 'test-field-name', - toastNotifications: discoverServiceMock.toastNotifications, + toastNotifications: servicesMock.toastNotifications, }); execCommandMock.mockImplementationOnce(() => true); @@ -49,9 +49,9 @@ describe('Build a column button to copy to clipboard', () => { const { label, iconType, onClick } = buildCopyColumnValuesButton({ columnId: 'extension', columnDisplayName: 'custom_extension', - toastNotifications: discoverServiceMock.toastNotifications, + toastNotifications: servicesMock.toastNotifications, rowsCount: 3, - valueToStringConverter: discoverGridContextMock.valueToStringConverter, + valueToStringConverter: dataTableContextMock.valueToStringConverter, }); const wrapper = mountWithIntl( @@ -72,8 +72,8 @@ describe('Build a column button to copy to clipboard', () => { } = buildCopyColumnValuesButton({ columnId: '_source', columnDisplayName: 'Document', - toastNotifications: discoverServiceMock.toastNotifications, - valueToStringConverter: discoverGridContextMock.valueToStringConverter, + toastNotifications: servicesMock.toastNotifications, + valueToStringConverter: dataTableContextMock.valueToStringConverter, rowsCount: 3, }); @@ -101,7 +101,7 @@ describe('Build a column button to copy to clipboard', () => { it('should not copy to clipboard on click', () => { const { label, iconType, onClick } = buildCopyColumnNameButton({ columnDisplayName: 'test-field-name', - toastNotifications: discoverServiceMock.toastNotifications, + toastNotifications: servicesMock.toastNotifications, }); execCommandMock.mockImplementationOnce(() => false); diff --git a/src/plugins/discover/public/components/discover_grid/build_copy_column_button.tsx b/packages/kbn-unified-data-table/src/components/build_copy_column_button.tsx similarity index 90% rename from src/plugins/discover/public/components/discover_grid/build_copy_column_button.tsx rename to packages/kbn-unified-data-table/src/components/build_copy_column_button.tsx index 111e80dd62e95..d1bfff1f1da41 100644 --- a/src/plugins/discover/public/components/discover_grid/build_copy_column_button.tsx +++ b/packages/kbn-unified-data-table/src/components/build_copy_column_button.tsx @@ -13,8 +13,8 @@ import type { ToastsStart } from '@kbn/core/public'; import { copyColumnValuesToClipboard, copyColumnNameToClipboard, -} from '../../utils/copy_value_to_clipboard'; -import type { ValueToStringConverter } from '../../types'; +} from '../utils/copy_value_to_clipboard'; +import type { ValueToStringConverter } from '../types'; function buildCopyColumnButton({ label, @@ -47,7 +47,7 @@ export function buildCopyColumnNameButton({ return buildCopyColumnButton({ label: ( ), @@ -72,7 +72,7 @@ export function buildCopyColumnValuesButton({ return buildCopyColumnButton({ label: ( ), diff --git a/src/plugins/discover/public/components/discover_grid/build_edit_field_button.test.tsx b/packages/kbn-unified-data-table/src/components/build_edit_field_button.test.tsx similarity index 81% rename from src/plugins/discover/public/components/discover_grid/build_edit_field_button.test.tsx rename to packages/kbn-unified-data-table/src/components/build_edit_field_button.test.tsx index c78918976e88d..a9d1a37ab6eda 100644 --- a/src/plugins/discover/public/components/discover_grid/build_edit_field_button.test.tsx +++ b/packages/kbn-unified-data-table/src/components/build_edit_field_button.test.tsx @@ -11,7 +11,7 @@ import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import React from 'react'; import { buildDataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { discoverServiceMock } from '../../__mocks__/services'; +import { servicesMock } from '../../__mocks__/services'; import { buildEditFieldButton } from './build_edit_field_button'; const dataView = buildDataViewMock({ @@ -50,8 +50,7 @@ describe('buildEditFieldButton', () => { it('should return null if the field is not editable', () => { const field = dataView.getFieldByName('unknown_field') as DataViewField; const button = buildEditFieldButton({ - hasEditDataViewPermission: () => - discoverServiceMock.dataViewEditor.userPermissions.editDataView(), + hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(), dataView, field, editField: jest.fn(), @@ -61,12 +60,11 @@ describe('buildEditFieldButton', () => { it('should return null if the data view is not editable', () => { jest - .spyOn(discoverServiceMock.dataViewEditor.userPermissions, 'editDataView') + .spyOn(servicesMock.dataViewEditor.userPermissions, 'editDataView') .mockReturnValueOnce(false); const field = dataView.getFieldByName('bytes') as DataViewField; const button = buildEditFieldButton({ - hasEditDataViewPermission: () => - discoverServiceMock.dataViewEditor.userPermissions.editDataView(), + hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(), dataView, field, editField: jest.fn(), @@ -77,8 +75,7 @@ describe('buildEditFieldButton', () => { it('should return null if passed the _source field', () => { const field = dataView.getFieldByName('_source') as DataViewField; const button = buildEditFieldButton({ - hasEditDataViewPermission: () => - discoverServiceMock.dataViewEditor.userPermissions.editDataView(), + hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(), dataView, field, editField: jest.fn(), @@ -89,8 +86,7 @@ describe('buildEditFieldButton', () => { it('should return EuiListGroupItemProps if the field and data view are editable', () => { const field = dataView.getFieldByName('bytes') as DataViewField; const button = buildEditFieldButton({ - hasEditDataViewPermission: () => - discoverServiceMock.dataViewEditor.userPermissions.editDataView(), + hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(), dataView, field, editField: jest.fn(), @@ -105,7 +101,7 @@ describe('buildEditFieldButton', () => { "iconType": "pencil", "label": , "onClick": [Function], @@ -118,8 +114,7 @@ describe('buildEditFieldButton', () => { const field = dataView.getFieldByName('bytes') as DataViewField; const editField = jest.fn(); const buttonProps = buildEditFieldButton({ - hasEditDataViewPermission: () => - discoverServiceMock.dataViewEditor.userPermissions.editDataView(), + hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(), dataView, field, editField, diff --git a/src/plugins/discover/public/components/discover_grid/build_edit_field_button.tsx b/packages/kbn-unified-data-table/src/components/build_edit_field_button.tsx similarity index 87% rename from src/plugins/discover/public/components/discover_grid/build_edit_field_button.tsx rename to packages/kbn-unified-data-table/src/components/build_edit_field_button.tsx index 71da6ca691f93..87d405f608c8c 100644 --- a/src/plugins/discover/public/components/discover_grid/build_edit_field_button.tsx +++ b/packages/kbn-unified-data-table/src/components/build_edit_field_button.tsx @@ -10,7 +10,7 @@ import { EuiListGroupItemProps } from '@elastic/eui'; import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; -import { getFieldCapabilities } from '../../utils/get_field_capabilities'; +import { getFieldCapabilities } from '../utils/get_field_capabilities'; export const buildEditFieldButton = ({ hasEditDataViewPermission, @@ -37,7 +37,10 @@ export const buildEditFieldButton = ({ const editFieldButton: EuiListGroupItemProps = { size: 'xs', label: ( - + ), iconType: 'pencil', iconProps: { size: 'm' }, diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid.scss b/packages/kbn-unified-data-table/src/components/data_table.scss similarity index 78% rename from src/plugins/discover/public/components/discover_grid/discover_grid.scss rename to packages/kbn-unified-data-table/src/components/data_table.scss index 0e870d366b609..8b0f8719a450f 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid.scss +++ b/packages/kbn-unified-data-table/src/components/data_table.scss @@ -1,4 +1,4 @@ -.dscDiscoverGrid { +.unifiedDataTable { width: 100%; max-width: 100%; height: 100%; @@ -19,8 +19,8 @@ border-right: none; } - .dscDiscoverGrid__table .euiDataGridRowCell:first-of-type, - .dscDiscoverGrid__table .euiDataGrid--headerShade.euiDataGrid--bordersAll .euiDataGridHeaderCell:first-of-type { + .unifiedDataTable__table .euiDataGridRowCell:first-of-type, + .unifiedDataTable__table .euiDataGrid--headerShade.euiDataGrid--bordersAll .euiDataGridHeaderCell:first-of-type { border-left: none; border-right: none; } @@ -31,11 +31,11 @@ } } -.dscDiscoverGrid__cellValue { +.unifiedDataTable__cellValue { font-family: $euiCodeFontFamily; } -.dscDiscoverGrid__cellPopover { +.unifiedDataTable__cellPopover { // Fixes https://github.com/elastic/kibana/issues/145216 in Chrome .lines-content.monaco-editor-background { overflow: unset !important; @@ -43,7 +43,7 @@ } } -.dscDiscoverGrid__cellPopoverValue { +.unifiedDataTable__cellPopoverValue { font-family: $euiCodeFontFamily; font-size: $euiFontSizeS; } @@ -52,24 +52,32 @@ white-space: pre-wrap; } -.dscDiscoverGrid__inner { +.unifiedDataTable__inner { display: flex; flex-direction: column; flex-wrap: nowrap; height: 100%; } -.dscDiscoverGrid__table { +.unifiedDataTable__table { flex-grow: 1; flex-shrink: 1; min-height: 0; } -.dscTable__flyoutHeader { +.unifiedDataTable__footer { + flex-shrink: 0; + background-color: $euiColorLightShade; + padding: $euiSize / 2 $euiSize; + margin-top: $euiSize / 4; + text-align: center; +} + +.unifiedDataTable__flyoutHeader { white-space: nowrap; } -.dscTable__flyoutDocumentNavigation { +.unifiedDataTable__flyoutDocumentNavigation { justify-content: flex-end; } @@ -106,11 +114,11 @@ width: 100%; } -.dscFormatSource { +.unifiedDataTableFormatSource { @include euiTextTruncate; } -.dscDiscoverGrid__descriptionListDescription { +.unifiedDataTable__descriptionListDescription { word-break: break-all; white-space: normal; @@ -132,7 +140,7 @@ @include euiBreakpoint('xs', 's', 'm') { // EUI issue to hide 'of' text https://github.com/elastic/eui/issues/4654 - .dscTable__flyoutDocumentNavigation .euiPagination__compressedText { + .unifiedDataTable__flyoutDocumentNavigation .euiPagination__compressedText { display: none; } } diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid.test.tsx b/packages/kbn-unified-data-table/src/components/data_table.test.tsx similarity index 61% rename from src/plugins/discover/public/components/discover_grid/discover_grid.test.tsx rename to packages/kbn-unified-data-table/src/components/data_table.test.tsx index 153126b4d471c..7ca0888230749 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid.test.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table.test.tsx @@ -7,16 +7,23 @@ */ import React from 'react'; import { ReactWrapper } from 'enzyme'; -import { EuiCopy } from '@elastic/eui'; +import { + EuiButton, + EuiCopy, + EuiDataGridCellValueElementProps, + EuiDataGridCustomBodyProps, +} from '@elastic/eui'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; import { act } from 'react-dom/test-utils'; import { findTestSubject } from '@elastic/eui/lib/test'; import { buildDataViewMock, deepMockedFields, esHitsMock } from '@kbn/discover-utils/src/__mocks__'; import { mountWithIntl } from '@kbn/test-jest-helpers'; -import { DiscoverGrid, DiscoverGridProps, DataLoadingState } from './discover_grid'; +import { DataLoadingState, UnifiedDataTable, UnifiedDataTableProps } from './data_table'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { discoverServiceMock } from '../../__mocks__/services'; +import { servicesMock } from '../../__mocks__/services'; import { buildDataTableRecord, getDocId } from '@kbn/discover-utils'; -import type { EsHitRecord } from '@kbn/discover-utils/types'; +import type { DataTableRecord, EsHitRecord } from '@kbn/discover-utils/types'; +import { testLeadingControlColumn } from '../../__mocks__/external_control_columns'; const mockUseDataGridColumnsCellActions = jest.fn((prop: unknown) => []); jest.mock('@kbn/cell-actions', () => ({ @@ -30,8 +37,8 @@ export const dataViewMock = buildDataViewMock({ timeFieldName: '@timestamp', }); -function getProps() { - const services = discoverServiceMock; +function getProps(): UnifiedDataTableProps { + const services = servicesMock; services.dataViewFieldEditor.userPermissions.editIndexPattern = jest.fn().mockReturnValue(true); return { @@ -40,9 +47,7 @@ function getProps() { dataView: dataViewMock, loadingState: DataLoadingState.loaded, expandedDoc: undefined, - onAddColumn: jest.fn(), onFilter: jest.fn(), - onRemoveColumn: jest.fn(), onResize: jest.fn(), onSetColumns: jest.fn(), onSort: jest.fn(), @@ -55,14 +60,22 @@ function getProps() { showTimeCol: true, sort: [], useNewFieldsApi: true, - services, + services: { + fieldFormats: services.fieldFormats, + uiSettings: services.uiSettings, + dataViewFieldEditor: services.dataViewFieldEditor, + toastNotifications: services.toastNotifications, + storage: services.storage as unknown as Storage, + data: services.data, + theme: services.theme, + }, }; } -async function getComponent(props: DiscoverGridProps = getProps()) { - const Proxy = (innerProps: DiscoverGridProps) => ( - - +async function getComponent(props: UnifiedDataTableProps = getProps()) { + const Proxy = (innerProps: UnifiedDataTableProps) => ( + + ); @@ -74,7 +87,7 @@ async function getComponent(props: DiscoverGridProps = getProps()) { return component; } -function getSelectedDocNr(component: ReactWrapper) { +function getSelectedDocNr(component: ReactWrapper) { const gridSelectionBtn = findTestSubject(component, 'dscGridSelectionBtn'); if (!gridSelectionBtn.length) { return 0; @@ -83,7 +96,7 @@ function getSelectedDocNr(component: ReactWrapper) { return Number(selectedNr); } -function getDisplayedDocNr(component: ReactWrapper) { +function getDisplayedDocNr(component: ReactWrapper) { const gridSelectionBtn = findTestSubject(component, 'discoverDocTable'); if (!gridSelectionBtn.length) { return 0; @@ -93,7 +106,7 @@ function getDisplayedDocNr(component: ReactWrapper) { } async function toggleDocSelection( - component: ReactWrapper, + component: ReactWrapper, document: EsHitRecord ) { act(() => { @@ -103,13 +116,13 @@ async function toggleDocSelection( component.update(); } -describe('DiscoverGrid', () => { +describe('UnifiedDataTable', () => { afterEach(async () => { jest.clearAllMocks(); }); describe('Document selection', () => { - let component: ReactWrapper; + let component: ReactWrapper; beforeEach(async () => { component = await getComponent(); }); @@ -287,4 +300,136 @@ describe('DiscoverGrid', () => { `); }); }); + + describe('externalControlColumns', () => { + it('should render external leading control columns', async () => { + const component = await getComponent({ + ...getProps(), + expandedDoc: { + id: 'test', + raw: { + _index: 'test_i', + _id: 'test', + }, + flattened: { test: jest.fn() }, + }, + setExpandedDoc: jest.fn(), + renderDocumentView: jest.fn(), + externalControlColumns: [testLeadingControlColumn], + }); + + expect(findTestSubject(component, 'docTableExpandToggleColumn').exists()).toBeTruthy(); + expect(findTestSubject(component, 'test-body-control-column-cell').exists()).toBeTruthy(); + }); + }); + + it('should render provided in renderDocumentView DocumentView on expand clicked', async () => { + const component = await getComponent({ + ...getProps(), + expandedDoc: { + id: 'test', + raw: { + _index: 'test_i', + _id: 'test', + }, + flattened: { test: jest.fn() }, + }, + setExpandedDoc: jest.fn(), + renderDocumentView: ( + hit: DataTableRecord, + displayedRows: DataTableRecord[], + displayedColumns: string[] + ) =>
    {hit.id}
    , + externalControlColumns: [testLeadingControlColumn], + }); + + findTestSubject(component, 'docTableExpandToggleColumn').first().simulate('click'); + expect(findTestSubject(component, 'test-document-view').exists()).toBeTruthy(); + }); + + describe('externalAdditionalControls', () => { + it('should render external additional toolbar controls', async () => { + const component = await getComponent({ + ...getProps(), + columns: ['message'], + externalAdditionalControls: , + }); + + expect(findTestSubject(component, 'test-additional-control').exists()).toBeTruthy(); + expect(findTestSubject(component, 'dataGridColumnSelectorButton').exists()).toBeTruthy(); + }); + }); + + describe('externalCustomRenderers', () => { + it('should render only host column with the custom renderer, message should be rendered with the default cell renderer', async () => { + const component = await getComponent({ + ...getProps(), + columns: ['message', 'host'], + externalCustomRenderers: { + host: (props: EuiDataGridCellValueElementProps) => ( +
    {props.columnId}
    + ), + }, + }); + + expect(findTestSubject(component, 'test-renderer-host').exists()).toBeTruthy(); + expect(findTestSubject(component, 'test-renderer-message').exists()).toBeFalsy(); + }); + }); + + describe('renderCustomGridBody', () => { + it('should render custom grid body for each row', async () => { + const component = await getComponent({ + ...getProps(), + columns: ['message', 'host'], + trailingControlColumns: [ + { + id: 'row-details', + + // The header cell should be visually hidden, but available to screen readers + width: 0, + headerCellRender: () => <>, + headerCellProps: { className: 'euiScreenReaderOnly' }, + + // The footer cell can be hidden to both visual & SR users, as it does not contain meaningful information + footerCellProps: { style: { display: 'none' } }, + + // When rendering this custom cell, we'll want to override + // the automatic width/heights calculated by EuiDataGrid + rowCellRender: jest.fn(), + }, + ], + renderCustomGridBody: (props: EuiDataGridCustomBodyProps) => ( +
    + +
    + ), + }); + + expect(findTestSubject(component, 'test-renderer-custom-grid-body').exists()).toBeTruthy(); + }); + }); + + describe('componentsTourSteps', () => { + it('should render tour step for the first row of leading control column expandButton', async () => { + const component = await getComponent({ + ...getProps(), + expandedDoc: { + id: 'test', + raw: { + _index: 'test_i', + _id: 'test', + }, + flattened: { test: jest.fn() }, + }, + setExpandedDoc: jest.fn(), + renderDocumentView: jest.fn(), + componentsTourSteps: { expandButton: 'test-expand' }, + }); + + const gridExpandBtn = findTestSubject(component, 'docTableExpandToggleColumn').first(); + const tourStep = gridExpandBtn.getDOMNode().getAttribute('id'); + expect(tourStep).toEqual('test-expand'); + }); + }); }); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx b/packages/kbn-unified-data-table/src/components/data_table.tsx similarity index 64% rename from src/plugins/discover/public/components/discover_grid/discover_grid.tsx rename to packages/kbn-unified-data-table/src/components/data_table.tsx index 414b8986e5cbc..e5f5e5dbbba39 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table.tsx @@ -11,7 +11,8 @@ import classnames from 'classnames'; import { FormattedMessage } from '@kbn/i18n-react'; import { of } from 'rxjs'; import useObservable from 'react-use/lib/useObservable'; -import './discover_grid.scss'; +import './data_table.scss'; +import type { Storage } from '@kbn/kibana-utils-plugin/public'; import { EuiDataGridSorting, EuiDataGrid, @@ -23,44 +24,42 @@ import { EuiIcon, EuiDataGridRefProps, EuiDataGridInMemory, + EuiDataGridControlColumn, + EuiDataGridCustomBodyProps, + EuiDataGridCellValueElementProps, } from '@elastic/eui'; import type { DataView } from '@kbn/data-views-plugin/public'; -import type { SortOrder } from '@kbn/saved-search-plugin/public'; import { useDataGridColumnsCellActions, type UseDataGridColumnsCellActionsProps, } from '@kbn/cell-actions'; -import type { AggregateQuery, Filter, Query } from '@kbn/es-query'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import type { ToastsStart, IUiSettingsClient, HttpStart, CoreStart } from '@kbn/core/public'; -import { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; -import { Serializable } from '@kbn/utility-types'; +import type { ToastsStart, IUiSettingsClient } from '@kbn/core/public'; +import type { Serializable } from '@kbn/utility-types'; import type { DataTableRecord } from '@kbn/discover-utils/types'; -import { getShouldShowFieldHandler } from '@kbn/discover-utils'; +import { getShouldShowFieldHandler, DOC_HIDE_TIME_COLUMN_SETTING } from '@kbn/discover-utils'; +import type { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; +import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import type { ThemeServiceStart } from '@kbn/react-kibana-context-common'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import { UnifiedDataTableSettings, ValueToStringConverter } from '../types'; +import { getDisplayedColumns } from '../utils/columns'; +import { convertValueToString } from '../utils/convert_value_to_string'; +import { getRowsPerPageOptions } from '../utils/rows_per_page'; +import { getRenderCellValueFn } from '../utils/get_render_cell_value'; +import { getEuiGridColumns, getLeadControlColumns, getVisibleColumns } from './data_table_columns'; +import { UnifiedDataTableContext } from '../table_context'; +import { getSchemaDetectors } from './data_table_schema'; +import { DataTableDocumentToolbarBtn } from './data_table_document_selection'; +import { useRowHeightsOptions } from '../hooks/use_row_heights_options'; import { - DOC_HIDE_TIME_COLUMN_SETTING, - MAX_DOC_FIELDS_DISPLAYED, - SHOW_MULTIFIELDS, -} from '@kbn/discover-utils'; -import { DocViewFilterFn } from '../../services/doc_views/doc_views_types'; -import { getSchemaDetectors } from './discover_grid_schema'; -import { DiscoverGridFlyout } from './discover_grid_flyout'; -import { DiscoverGridContext } from './discover_grid_context'; -import { getRenderCellValueFn } from './get_render_cell_value'; -import { DiscoverGridSettings } from './types'; -import { - getEuiGridColumns, - getLeadControlColumns, - getVisibleColumns, -} from './discover_grid_columns'; -import { GRID_STYLE, toolbarVisibility as toolbarVisibilityDefaults } from './constants'; -import { getDisplayedColumns } from '../../utils/columns'; -import { DiscoverGridDocumentToolbarBtn } from './discover_grid_document_selection'; -import { DiscoverGridFooter } from './discover_grid_footer'; -import type { ValueToStringConverter } from '../../types'; -import { useRowHeightsOptions } from '../../hooks/use_row_heights_options'; -import { convertValueToString } from '../../utils/convert_value_to_string'; -import { getRowsPerPageOptions, getDefaultRowsPerPage } from '../../utils/rows_per_page'; + DEFAULT_ROWS_PER_PAGE, + GRID_STYLE, + toolbarVisibility as toolbarVisibilityDefaults, +} from '../constants'; +import { UnifiedDataTableFooter } from './data_table_footer'; + +export type SortOrder = [string, string]; export enum DataLoadingState { loading = 'loading', @@ -75,7 +74,7 @@ interface SortObj { direction: string; } -export interface DiscoverGridProps { +export interface UnifiedDataTableProps { /** * Determines which element labels the grid for ARIA */ @@ -85,7 +84,7 @@ export interface DiscoverGridProps { */ className?: string; /** - * Determines which columns are displayed + * Determines ids of the columns which are displayed */ columns: string[]; /** @@ -100,19 +99,10 @@ export interface DiscoverGridProps { * Determines if data is currently loaded */ loadingState: DataLoadingState; - /** - * Function used to add a column in the document flyout - */ - onAddColumn: (column: string) => void; /** * Function to add a filter in the grid cell or document flyout */ onFilter: DocViewFilterFn; - /** - * Function used in the grid header and flyout to remove a column - * @param column - */ - onRemoveColumn: (column: string) => void; /** * Function triggered when a column is resized by the user */ @@ -140,13 +130,13 @@ export interface DiscoverGridProps { /** * Grid display settings persisted in Elasticsearch (e.g. column width) */ - settings?: DiscoverGridSettings; + settings?: UnifiedDataTableSettings; /** - * Saved search description + * Search description */ searchDescription?: string; /** - * Saved search title + * Search title */ searchTitle?: string; /** @@ -201,22 +191,6 @@ export interface DiscoverGridProps { * Callback to execute on edit runtime field */ onFieldEdited?: () => void; - /** - * Filters applied by saved search embeddable - */ - filters?: Filter[]; - /** - * Query applied by KQL bar or text based editor - */ - query?: Query | AggregateQuery; - /** - * Saved search id used for links to single doc and surrounding docs in the flyout - */ - savedSearchId?: string; - /** - * Document detail view component - */ - DocumentView?: typeof DiscoverGridFlyout; /** * Optional triggerId to retrieve the column cell actions that will override the default ones */ @@ -225,13 +199,38 @@ export interface DiscoverGridProps { * Service dependencies */ services: { - core: CoreStart; + theme: ThemeServiceStart; fieldFormats: FieldFormatsStart; - addBasePath: HttpStart['basePath']['prepend']; uiSettings: IUiSettingsClient; dataViewFieldEditor: DataViewFieldEditorStart; toastNotifications: ToastsStart; + storage: Storage; + data: DataPublicPluginStart; }; + /** + * Callback to render DocumentView when the document is expanded + */ + renderDocumentView?: ( + hit: DataTableRecord, + displayedRows: DataTableRecord[], + displayedColumns: string[] + ) => JSX.Element | undefined; + /** + * Optional value for providing configuration setting for UnifiedDataTable rows height + */ + configRowHeight?: number; + /** + * Optional value for providing configuration setting for enabling to display the complex fields in the table. Default is true. + */ + showMultiFields?: boolean; + /** + * Optional value for providing configuration setting for maximum number of document fields to display in the table. Default is 50. + */ + maxDocFieldsDisplayed?: number; + /** + * Optional value for providing EuiDataGridControlColumn list of the additional leading control columns. UnifiedDataTable includes two control columns: Open Details and Select. + */ + externalControlColumns?: EuiDataGridControlColumn[]; /** * Number total hits from ES */ @@ -240,24 +239,62 @@ export interface DiscoverGridProps { * To fetch more */ onFetchMoreRecords?: () => void; + /** + * Optional value for providing the additional controls available in the UnifiedDataTable toolbar to manage it's records or state. UnifiedDataTable includes Columns, Sorting and Bulk Actions. + */ + externalAdditionalControls?: React.ReactNode; + /** + * Optional list of number type values to set custom UnifiedDataTable paging options to display the records per page. + */ + rowsPerPageOptions?: number[]; + /** + * An optional function called to completely customize and control the rendering of + * EuiDataGrid's body and cell placement. This can be used to, e.g. remove EuiDataGrid's + * virtualization library, or roll your own. + * + * This component is **only** meant as an escape hatch for extremely custom use cases. + * + * Behind the scenes, this function is treated as a React component, + * allowing hooks, context, and other React concepts to be used. + * It receives #EuiDataGridCustomBodyProps as its only argument. + */ + renderCustomGridBody?: (args: EuiDataGridCustomBodyProps) => React.ReactNode; + /** + * An optional list of the EuiDataGridControlColumn type for setting trailing control columns standard for EuiDataGrid. + */ + trailingControlColumns?: EuiDataGridControlColumn[]; + /** + * An optional value for a custom number of the visible cell actions in the table. By default is up to 3. + **/ + visibleCellActions?: number; + /** + * An optional settings for a specified fields rendering like links. Applied only for the listed fields rendering. + */ + externalCustomRenderers?: Record< + string, + (props: EuiDataGridCellValueElementProps) => React.ReactNode + >; + /** + * Name of the UnifiedDataTable consumer component or application + */ + consumer?: string; + /** + * Optional key/value pairs to set guided onboarding steps ids for a data table components included to guided tour. + */ + componentsTourSteps?: Record; } export const EuiDataGridMemoized = React.memo(EuiDataGrid); const CONTROL_COLUMN_IDS_DEFAULT = ['openDetails', 'select']; -export const DiscoverGrid = ({ +export const UnifiedDataTable = ({ ariaLabelledBy, columns, + controlColumnIds = CONTROL_COLUMN_IDS_DEFAULT, dataView, loadingState, - expandedDoc, - onAddColumn, - filters, - query, - savedSearchId, onFilter, - onRemoveColumn, onResize, onSetColumns, onSort, @@ -265,7 +302,6 @@ export const DiscoverGrid = ({ sampleSize, searchDescription, searchTitle, - setExpandedDoc, settings, showTimeCol, showFullScreenButton = true, @@ -273,7 +309,6 @@ export const DiscoverGrid = ({ useNewFieldsApi, isSortEnabled = true, isPaginationEnabled = true, - controlColumnIds = CONTROL_COLUMN_IDS_DEFAULT, cellActionsTriggerId, className, rowHeightState, @@ -282,13 +317,28 @@ export const DiscoverGrid = ({ rowsPerPageState, onUpdateRowsPerPage, onFieldEdited, - DocumentView, services, + renderCustomGridBody, + trailingControlColumns, totalHits, onFetchMoreRecords, -}: DiscoverGridProps) => { - const { fieldFormats, toastNotifications, dataViewFieldEditor, uiSettings } = services; - const { darkMode } = useObservable(services.core.theme?.theme$ ?? of(themeDefault), themeDefault); + renderDocumentView, + setExpandedDoc, + expandedDoc, + configRowHeight, + showMultiFields = true, + maxDocFieldsDisplayed = 50, + externalControlColumns, + externalAdditionalControls, + rowsPerPageOptions, + visibleCellActions, + externalCustomRenderers, + consumer = 'discover', + componentsTourSteps, +}: UnifiedDataTableProps) => { + const { fieldFormats, toastNotifications, dataViewFieldEditor, uiSettings, storage, data } = + services; + const { darkMode } = useObservable(services.theme?.theme$ ?? of(themeDefault), themeDefault); const dataGridRef = useRef(null); const [selectedDocs, setSelectedDocs] = useState([]); const [isFilterActive, setIsFilterActive] = useState(false); @@ -300,7 +350,7 @@ export const DiscoverGrid = ({ } const idMap = rows.reduce((map, row) => map.set(row.id, true), new Map()); // filter out selected docs that are no longer part of the current data - const result = selectedDocs.filter((docId) => idMap.get(docId)); + const result = selectedDocs.filter((docId) => !!idMap.get(docId)); if (result.length === 0 && isFilterActive) { setIsFilterActive(false); } @@ -336,17 +386,45 @@ export const DiscoverGrid = ({ [displayedRows, dataView, fieldFormats] ); + const unifiedDataTableContextValue = useMemo( + () => ({ + expanded: expandedDoc, + setExpanded: setExpandedDoc, + rows: displayedRows, + onFilter, + dataView, + isDarkMode: darkMode, + selectedDocs: usedSelectedDocs, + setSelectedDocs: (newSelectedDocs: React.SetStateAction) => { + setSelectedDocs(newSelectedDocs); + if (isFilterActive && newSelectedDocs.length === 0) { + setIsFilterActive(false); + } + }, + valueToStringConverter, + componentsTourSteps, + }), + [ + componentsTourSteps, + darkMode, + dataView, + displayedRows, + expandedDoc, + isFilterActive, + onFilter, + setExpandedDoc, + usedSelectedDocs, + valueToStringConverter, + ] + ); + /** * Pagination */ - const defaultRowsPerPage = useMemo( - () => getDefaultRowsPerPage(services.uiSettings), - [services.uiSettings] - ); const currentPageSize = typeof rowsPerPageState === 'number' && rowsPerPageState > 0 ? rowsPerPageState - : defaultRowsPerPage; + : DEFAULT_ROWS_PER_PAGE; const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: currentPageSize, @@ -371,10 +449,17 @@ export const DiscoverGrid = ({ onChangePage, pageIndex: pagination.pageIndex > pageCount - 1 ? 0 : pagination.pageIndex, pageSize: pagination.pageSize, - pageSizeOptions: getRowsPerPageOptions(pagination.pageSize), + pageSizeOptions: rowsPerPageOptions ?? getRowsPerPageOptions(pagination.pageSize), } : undefined; - }, [pagination, pageCount, isPaginationEnabled, onUpdateRowsPerPage]); + }, [ + isPaginationEnabled, + pagination.pageIndex, + pagination.pageSize, + pageCount, + rowsPerPageOptions, + onUpdateRowsPerPage, + ]); useEffect(() => { setPagination((paginationData) => @@ -403,8 +488,6 @@ export const DiscoverGrid = ({ [onSort, isSortEnabled, isPlainRecord, setInmemorySortingColumns] ); - const showMultiFields = services.uiSettings.get(SHOW_MULTIFIELDS); - const shouldShowFieldHandler = useMemo(() => { const dataViewFields = dataView.fields.getAll().map((fld) => fld.name); return getShouldShowFieldHandler(dataViewFields, dataView, showMultiFields); @@ -420,10 +503,20 @@ export const DiscoverGrid = ({ displayedRows, useNewFieldsApi, shouldShowFieldHandler, - services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED), - () => dataGridRef.current?.closeCellPopover() + () => dataGridRef.current?.closeCellPopover(), + services.fieldFormats, + maxDocFieldsDisplayed, + externalCustomRenderers ), - [dataView, displayedRows, useNewFieldsApi, shouldShowFieldHandler, services.uiSettings] + [ + dataView, + displayedRows, + useNewFieldsApi, + shouldShowFieldHandler, + maxDocFieldsDisplayed, + services.fieldFormats, + externalCustomRenderers, + ] ); /** @@ -459,7 +552,7 @@ export const DiscoverGrid = ({ ); const visibleColumns = useMemo( - () => getVisibleColumns(displayedColumns, dataView, showTimeCol) as string[], + () => getVisibleColumns(displayedColumns, dataView, showTimeCol), [dataView, displayedColumns, showTimeCol] ); @@ -511,6 +604,7 @@ export const DiscoverGrid = ({ valueToStringConverter, onFilter, editField, + visibleCellActions, }), [ onFilter, @@ -527,6 +621,7 @@ export const DiscoverGrid = ({ dataViewFieldEditor, valueToStringConverter, editField, + visibleCellActions, ] ); @@ -554,26 +649,33 @@ export const DiscoverGrid = ({ return { columns: sortingColumns, onSort: () => {} }; }, [isSortEnabled, sortingColumns, isPlainRecord, inmemorySortingColumns, onTableSort]); - const canSetExpandedDoc = Boolean(setExpandedDoc && DocumentView); + const canSetExpandedDoc = Boolean(setExpandedDoc && !!renderDocumentView); - const lead = useMemo( - () => - getLeadControlColumns(canSetExpandedDoc).filter(({ id }) => controlColumnIds.includes(id)), - [controlColumnIds, canSetExpandedDoc] - ); + const leadingControlColumns = useMemo(() => { + const internalControlColumns = getLeadControlColumns(canSetExpandedDoc).filter(({ id }) => + controlColumnIds.includes(id) + ); + return externalControlColumns + ? [...internalControlColumns, ...externalControlColumns] + : internalControlColumns; + }, [canSetExpandedDoc, externalControlColumns, controlColumnIds]); const additionalControls = useMemo( - () => - usedSelectedDocs.length ? ( - - ) : null, - [usedSelectedDocs, isFilterActive, rows, setIsFilterActive] + () => ( + <> + {usedSelectedDocs.length ? ( + + ) : null} + {externalAdditionalControls} + + ), + [usedSelectedDocs, isFilterActive, rows, externalAdditionalControls] ); const showDisplaySelector = useMemo( @@ -588,8 +690,10 @@ export const DiscoverGrid = ({ ); const inMemory = useMemo(() => { - return isPlainRecord ? ({ level: 'sorting' } as EuiDataGridInMemory) : undefined; - }, [isPlainRecord]); + return isPlainRecord && columns.length + ? ({ level: 'sorting' } as EuiDataGridInMemory) + : undefined; + }, [columns.length, isPlainRecord]); const toolbarVisibility = useMemo( () => @@ -615,17 +719,20 @@ export const DiscoverGrid = ({ const rowHeightsOptions = useRowHeightsOptions({ rowHeightState, onUpdateRowHeight, + storage, + configRowHeight, + consumer, }); const isRenderComplete = loadingState !== DataLoadingState.loading; if (!rowCount && loadingState === DataLoadingState.loading) { return ( -
    +
    - +
    ); @@ -644,32 +751,18 @@ export const DiscoverGrid = ({ - +
    ); } return ( - { - setSelectedDocs(newSelectedDocs); - if (isFilterActive && newSelectedDocs.length === 0) { - setIsFilterActive(false); - } - }, - valueToStringConverter, - }} - > - + +
    {loadingState !== DataLoadingState.loading && isPaginationEnabled && ( // we hide the footer for Surrounding Documents page - )} {searchTitle && ( @@ -716,13 +813,13 @@ export const DiscoverGrid = ({

    {searchDescription ? ( ) : ( @@ -730,24 +827,10 @@ export const DiscoverGrid = ({

    )} - {setExpandedDoc && expandedDoc && DocumentView && ( - setExpandedDoc(undefined)} - setExpandedDoc={setExpandedDoc} - query={query} - /> - )} + {canSetExpandedDoc && + expandedDoc && + renderDocumentView!(expandedDoc, displayedRows, displayedColumns)}
    -
    + ); }; diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_columns.test.tsx b/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx similarity index 86% rename from src/plugins/discover/public/components/discover_grid/discover_grid_columns.test.tsx rename to packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx index cea7f6c3505c9..01246603643fd 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_columns.test.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx @@ -7,10 +7,10 @@ */ import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { getEuiGridColumns, getVisibleColumns } from './discover_grid_columns'; +import { getEuiGridColumns, getVisibleColumns } from './data_table_columns'; import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; -import { discoverGridContextMock } from '../../__mocks__/grid_context'; -import { discoverServiceMock } from '../../__mocks__/services'; +import { dataTableContextMock } from '../../__mocks__/table_context'; +import { servicesMock } from '../../__mocks__/services'; const columns = ['extension', 'message']; const columnsWithTimeCol = getVisibleColumns( @@ -19,7 +19,7 @@ const columnsWithTimeCol = getVisibleColumns( true ) as string[]; -describe('Discover grid columns', function () { +describe('Data table columns', function () { describe('getEuiGridColumns', () => { it('returns eui grid columns showing default columns', async () => { const actual = getEuiGridColumns({ @@ -29,14 +29,14 @@ describe('Discover grid columns', function () { defaultColumns: true, isSortEnabled: true, isPlainRecord: false, - valueToStringConverter: discoverGridContextMock.valueToStringConverter, + valueToStringConverter: dataTableContextMock.valueToStringConverter, rowsCount: 100, services: { - uiSettings: discoverServiceMock.uiSettings, - toastNotifications: discoverServiceMock.toastNotifications, + uiSettings: servicesMock.uiSettings, + toastNotifications: servicesMock.toastNotifications, }, hasEditDataViewPermission: () => - discoverServiceMock.dataViewFieldEditor.userPermissions.editIndexPattern(), + servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(), onFilter: () => {}, }); expect(actual).toMatchInlineSnapshot(` @@ -52,7 +52,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -66,7 +66,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -86,6 +86,7 @@ describe('Discover grid columns', function () { "id": "extension", "isSortable": false, "schema": "string", + "visibleCellActions": undefined, }, Object { "actions": Object { @@ -98,7 +99,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -112,7 +113,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -130,6 +131,7 @@ describe('Discover grid columns', function () { "id": "message", "isSortable": false, "schema": "string", + "visibleCellActions": undefined, }, ] `); @@ -143,14 +145,14 @@ describe('Discover grid columns', function () { defaultColumns: false, isSortEnabled: true, isPlainRecord: false, - valueToStringConverter: discoverGridContextMock.valueToStringConverter, + valueToStringConverter: dataTableContextMock.valueToStringConverter, rowsCount: 100, services: { - uiSettings: discoverServiceMock.uiSettings, - toastNotifications: discoverServiceMock.toastNotifications, + uiSettings: servicesMock.uiSettings, + toastNotifications: servicesMock.toastNotifications, }, hasEditDataViewPermission: () => - discoverServiceMock.dataViewFieldEditor.userPermissions.editIndexPattern(), + servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(), onFilter: () => {}, }); expect(actual).toMatchInlineSnapshot(` @@ -166,7 +168,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -180,7 +182,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -219,6 +221,7 @@ describe('Discover grid columns', function () { "initialWidth": 210, "isSortable": true, "schema": "datetime", + "visibleCellActions": undefined, }, Object { "actions": Object { @@ -231,7 +234,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -245,7 +248,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -268,6 +271,7 @@ describe('Discover grid columns', function () { "id": "extension", "isSortable": false, "schema": "string", + "visibleCellActions": undefined, }, Object { "actions": Object { @@ -280,7 +284,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -294,7 +298,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -315,6 +319,7 @@ describe('Discover grid columns', function () { "id": "message", "isSortable": false, "schema": "string", + "visibleCellActions": undefined, }, ] `); @@ -328,14 +333,14 @@ describe('Discover grid columns', function () { defaultColumns: false, isSortEnabled: true, isPlainRecord: true, - valueToStringConverter: discoverGridContextMock.valueToStringConverter, + valueToStringConverter: dataTableContextMock.valueToStringConverter, rowsCount: 100, services: { - uiSettings: discoverServiceMock.uiSettings, - toastNotifications: discoverServiceMock.toastNotifications, + uiSettings: servicesMock.uiSettings, + toastNotifications: servicesMock.toastNotifications, }, hasEditDataViewPermission: () => - discoverServiceMock.dataViewFieldEditor.userPermissions.editIndexPattern(), + servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(), onFilter: () => {}, }); expect(actual).toMatchInlineSnapshot(` @@ -351,7 +356,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -365,7 +370,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -404,6 +409,7 @@ describe('Discover grid columns', function () { "initialWidth": 210, "isSortable": true, "schema": "datetime", + "visibleCellActions": undefined, }, Object { "actions": Object { @@ -416,7 +422,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -430,7 +436,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -453,6 +459,7 @@ describe('Discover grid columns', function () { "id": "extension", "isSortable": true, "schema": "string", + "visibleCellActions": undefined, }, Object { "actions": Object { @@ -465,7 +472,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -479,7 +486,7 @@ describe('Discover grid columns', function () { "iconType": "copyClipboard", "label": , "onClick": [Function], @@ -500,6 +507,7 @@ describe('Discover grid columns', function () { "id": "message", "isSortable": true, "schema": "string", + "visibleCellActions": undefined, }, ] `); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_columns.tsx b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx similarity index 82% rename from src/plugins/discover/public/components/discover_grid/discover_grid_columns.tsx rename to packages/kbn-unified-data-table/src/components/data_table_columns.tsx index a93b8a9ff1464..4b66f2a2bd6cf 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_columns.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx @@ -17,14 +17,14 @@ import { } from '@elastic/eui'; import type { DataView } from '@kbn/data-views-plugin/public'; import { ToastsStart, IUiSettingsClient } from '@kbn/core/public'; -import { DocViewFilterFn } from '../../services/doc_views/doc_views_types'; -import { ExpandButton } from './discover_grid_expand_button'; -import { DiscoverGridSettings } from './types'; -import type { ValueToStringConverter } from '../../types'; -import { buildCellActions } from './discover_grid_cell_actions'; -import { getSchemaByKbnType } from './discover_grid_schema'; -import { SelectButton } from './discover_grid_document_selection'; -import { defaultTimeColumnWidth } from './constants'; +import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import { ExpandButton } from './data_table_expand_button'; +import { UnifiedDataTableSettings } from '../types'; +import type { ValueToStringConverter } from '../types'; +import { buildCellActions } from './default_cell_actions'; +import { getSchemaByKbnType } from './data_table_schema'; +import { SelectButton } from './data_table_document_selection'; +import { defaultTimeColumnWidth } from '../constants'; import { buildCopyColumnNameButton, buildCopyColumnValuesButton } from './build_copy_column_button'; import { buildEditFieldButton } from './build_edit_field_button'; @@ -34,7 +34,7 @@ const openDetails = { headerCellRender: () => ( - {i18n.translate('discover.controlColumnHeader', { + {i18n.translate('unifiedDataTable.controlColumnHeader', { defaultMessage: 'Control column', })} @@ -50,7 +50,7 @@ const select = { headerCellRender: () => ( - {i18n.translate('discover.selectColumnHeader', { + {i18n.translate('unifiedDataTable.selectColumnHeader', { defaultMessage: 'Select column', })} @@ -79,6 +79,7 @@ function buildEuiGridColumn({ onFilter, editField, columnCellActions, + visibleCellActions, }: { columnName: string; columnWidth: number | undefined; @@ -93,6 +94,7 @@ function buildEuiGridColumn({ onFilter?: DocViewFilterFn; editField?: (fieldName: string) => void; columnCellActions?: EuiDataGridColumnCellAction[]; + visibleCellActions?: number; }) { const dataViewField = dataView.getFieldByName(columnName); const editFieldButton = @@ -101,16 +103,19 @@ function buildEuiGridColumn({ buildEditFieldButton({ hasEditDataViewPermission, dataView, field: dataViewField, editField }); const columnDisplayName = columnName === '_source' - ? i18n.translate('discover.grid.documentHeader', { + ? i18n.translate('unifiedDataTable.grid.documentHeader', { defaultMessage: 'Document', }) : dataViewField?.displayName || columnName; let cellActions: EuiDataGridColumnCellAction[]; + if (columnCellActions?.length) { cellActions = columnCellActions; } else { - cellActions = dataViewField ? buildCellActions(dataViewField, onFilter) : []; + cellActions = dataViewField + ? buildCellActions(dataViewField, toastNotifications, valueToStringConverter, onFilter) + : []; } const column: EuiDataGridColumn = { @@ -123,7 +128,7 @@ function buildEuiGridColumn({ defaultColumns || columnName === dataView.timeFieldName ? false : { - label: i18n.translate('discover.removeColumnLabel', { + label: i18n.translate('unifiedDataTable.removeColumnLabel', { defaultMessage: 'Remove column', }), iconType: 'cross', @@ -150,23 +155,21 @@ function buildEuiGridColumn({ ], }, cellActions, + visibleCellActions, }; if (column.id === dataView.timeFieldName) { const timeFieldName = dataViewField?.customLabel ?? dataView.timeFieldName; const primaryTimeAriaLabel = i18n.translate( - 'discover.docTable.tableHeader.timeFieldIconTooltipAriaLabel', + 'unifiedDataTable.tableHeader.timeFieldIconTooltipAriaLabel', { defaultMessage: '{timeFieldName} - this field represents the time that events occurred.', values: { timeFieldName }, } ); - const primaryTimeTooltip = i18n.translate( - 'discover.docTable.tableHeader.timeFieldIconTooltip', - { - defaultMessage: 'This field represents the time that events occurred.', - } - ); + const primaryTimeTooltip = i18n.translate('unifiedDataTable.tableHeader.timeFieldIconTooltip', { + defaultMessage: 'This field represents the time that events occurred.', + }); column.display = (
    @@ -199,11 +202,12 @@ export function getEuiGridColumns({ valueToStringConverter, onFilter, editField, + visibleCellActions, }: { columns: string[]; columnsCellActions?: EuiDataGridColumnCellAction[][]; rowsCount: number; - settings: DiscoverGridSettings | undefined; + settings: UnifiedDataTableSettings | undefined; dataView: DataView; defaultColumns: boolean; isSortEnabled: boolean; @@ -216,6 +220,7 @@ export function getEuiGridColumns({ valueToStringConverter: ValueToStringConverter; onFilter: DocViewFilterFn; editField?: (fieldName: string) => void; + visibleCellActions?: number; }) { const getColWidth = (column: string) => settings?.columns?.[column]?.width ?? 0; @@ -234,6 +239,7 @@ export function getEuiGridColumns({ rowsCount, onFilter, editField, + visibleCellActions, }) ); } diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.test.tsx b/packages/kbn-unified-data-table/src/components/data_table_document_selection.test.tsx similarity index 79% rename from src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.test.tsx rename to packages/kbn-unified-data-table/src/components/data_table_document_selection.test.tsx index 7fda5b74ce550..ca0d422948416 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.test.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_document_selection.test.tsx @@ -8,9 +8,9 @@ import React from 'react'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { findTestSubject } from '@elastic/eui/lib/test'; -import { DiscoverGridDocumentToolbarBtn, SelectButton } from './discover_grid_document_selection'; -import { discoverGridContextMock } from '../../__mocks__/grid_context'; -import { DiscoverGridContext } from './discover_grid_context'; +import { DataTableDocumentToolbarBtn, SelectButton } from './data_table_document_selection'; +import { dataTableContextMock } from '../../__mocks__/table_context'; +import { UnifiedDataTableContext } from '../table_context'; import { getDocId } from '@kbn/discover-utils'; describe('document selection', () => { @@ -35,11 +35,11 @@ describe('document selection', () => { describe('SelectButton', () => { test('is not checked', () => { const contextMock = { - ...discoverGridContextMock, + ...dataTableContextMock, }; const component = mountWithIntl( - + { isDetails={false} isExpandable={false} /> - + ); const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); @@ -58,12 +58,12 @@ describe('document selection', () => { test('is checked', () => { const contextMock = { - ...discoverGridContextMock, + ...dataTableContextMock, selectedDocs: ['i::1::'], }; const component = mountWithIntl( - + { isDetails={false} isExpandable={false} /> - + ); const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); @@ -82,11 +82,11 @@ describe('document selection', () => { test('adding a selection', () => { const contextMock = { - ...discoverGridContextMock, + ...dataTableContextMock, }; const component = mountWithIntl( - + { isDetails={false} isExpandable={false} /> - + ); const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); @@ -105,12 +105,12 @@ describe('document selection', () => { }); test('removing a selection', () => { const contextMock = { - ...discoverGridContextMock, + ...dataTableContextMock, selectedDocs: ['i::1::'], }; const component = mountWithIntl( - + { isDetails={false} isExpandable={false} /> - + ); const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); @@ -128,16 +128,16 @@ describe('document selection', () => { expect(contextMock.setSelectedDocs).toHaveBeenCalledWith([]); }); }); - describe('DiscoverGridDocumentToolbarBtn', () => { + describe('DataTableDocumentToolbarBtn', () => { test('it renders a button clickable button', () => { const props = { isFilterActive: false, - rows: discoverGridContextMock.rows, + rows: dataTableContextMock.rows, selectedDocs: ['i::1::'], setIsFilterActive: jest.fn(), setSelectedDocs: jest.fn(), }; - const component = mountWithIntl(); + const component = mountWithIntl(); const button = findTestSubject(component, 'dscGridSelectionBtn'); expect(button.length).toBe(1); }); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.tsx b/packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx similarity index 89% rename from src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.tsx rename to packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx index f14ec323f8ca2..213e24790e840 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx @@ -20,15 +20,15 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { euiDarkVars as themeDark, euiLightVars as themeLight } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; import type { DataTableRecord } from '@kbn/discover-utils/types'; -import { DiscoverGridContext } from './discover_grid_context'; +import { UnifiedDataTableContext } from '../table_context'; export const SelectButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => { const { selectedDocs, expanded, rows, isDarkMode, setSelectedDocs } = - useContext(DiscoverGridContext); + useContext(UnifiedDataTableContext); const doc = useMemo(() => rows[rowIndex], [rows, rowIndex]); const checked = useMemo(() => selectedDocs.includes(doc.id), [selectedDocs, doc.id]); - const toggleDocumentSelectionLabel = i18n.translate('discover.grid.selectDoc', { + const toggleDocumentSelectionLabel = i18n.translate('unifiedDataTable.grid.selectDoc', { defaultMessage: `Select document '{rowNumber}'`, values: { rowNumber: rowIndex + 1 }, }); @@ -63,7 +63,7 @@ export const SelectButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle ); }; -export function DiscoverGridDocumentToolbarBtn({ +export function DataTableDocumentToolbarBtn({ isFilterActive, rows, selectedDocs, @@ -90,7 +90,10 @@ export function DiscoverGridDocumentToolbarBtn({ setIsFilterActive(false); }} > - + ) : ( @@ -122,7 +125,7 @@ export function DiscoverGridDocumentToolbarBtn({ {(copy) => ( @@ -138,7 +141,7 @@ export function DiscoverGridDocumentToolbarBtn({ setIsFilterActive(false); }} > - + , ]; }, [ @@ -176,7 +179,7 @@ export function DiscoverGridDocumentToolbarBtn({ })} > diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.test.tsx b/packages/kbn-unified-data-table/src/components/data_table_expand_button.test.tsx similarity index 70% rename from src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.test.tsx rename to packages/kbn-unified-data-table/src/components/data_table_expand_button.test.tsx index e95853b99b7b7..56d6d3ae3ce0e 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.test.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_expand_button.test.tsx @@ -9,18 +9,18 @@ import React from 'react'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { findTestSubject } from '@elastic/eui/lib/test'; -import { ExpandButton } from './discover_grid_expand_button'; -import { DiscoverGridContext } from './discover_grid_context'; -import { discoverGridContextMock } from '../../__mocks__/grid_context'; +import { ExpandButton } from './data_table_expand_button'; +import { UnifiedDataTableContext } from '../table_context'; +import { dataTableContextMock } from '../../__mocks__/table_context'; -describe('Discover grid view button ', function () { +describe('Data table view button ', function () { it('when no document is expanded, setExpanded is called with current document', async () => { const contextMock = { - ...discoverGridContextMock, + ...dataTableContextMock, }; const component = mountWithIntl( - + - + ); const button = findTestSubject(component, 'docTableExpandToggleColumn'); await button.simulate('click'); - expect(contextMock.setExpanded).toHaveBeenCalledWith(discoverGridContextMock.rows[0]); + expect(contextMock.setExpanded).toHaveBeenCalledWith(dataTableContextMock.rows[0]); }); it('when the current document is expanded, setExpanded is called with undefined', async () => { const contextMock = { - ...discoverGridContextMock, - expanded: discoverGridContextMock.rows[0], + ...dataTableContextMock, + expanded: dataTableContextMock.rows[0], }; const component = mountWithIntl( - + - + ); const button = findTestSubject(component, 'docTableExpandToggleColumn'); await button.simulate('click'); @@ -61,12 +61,12 @@ describe('Discover grid view button ', function () { }); it('when another document is expanded, setExpanded is called with the current document', async () => { const contextMock = { - ...discoverGridContextMock, - expanded: discoverGridContextMock.rows[0], + ...dataTableContextMock, + expanded: dataTableContextMock.rows[0], }; const component = mountWithIntl( - + - + ); const button = findTestSubject(component, 'docTableExpandToggleColumn'); await button.simulate('click'); - expect(contextMock.setExpanded).toHaveBeenCalledWith(discoverGridContextMock.rows[1]); + expect(contextMock.setExpanded).toHaveBeenCalledWith(dataTableContextMock.rows[1]); }); }); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx b/packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx similarity index 86% rename from src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx rename to packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx index 1a127f3639432..108ffaa4ec5fe 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx @@ -10,8 +10,7 @@ import React, { useContext, useEffect, useRef, useState } from 'react'; import { EuiButtonIcon, EuiDataGridCellValueElementProps, EuiToolTip } from '@elastic/eui'; import { euiLightVars as themeLight, euiDarkVars as themeDark } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; -import { DiscoverGridContext } from './discover_grid_context'; -import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../discover_tour'; +import { UnifiedDataTableContext } from '../table_context'; /** * Button to expand a given row @@ -19,9 +18,11 @@ import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../discover_tour'; export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => { const toolTipRef = useRef(null); const [pressed, setPressed] = useState(false); - const { expanded, setExpanded, rows, isDarkMode } = useContext(DiscoverGridContext); + const { expanded, setExpanded, rows, isDarkMode, componentsTourSteps } = + useContext(UnifiedDataTableContext); const current = rows[rowIndex]; + const tourStep = componentsTourSteps ? componentsTourSteps.expandButton : undefined; useEffect(() => { if (current.isAnchor) { setCellProps({ @@ -39,7 +40,7 @@ export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle }, [expanded, current, setCellProps, isDarkMode]); const isCurrentRowExpanded = current === expanded; - const buttonLabel = i18n.translate('discover.grid.viewDoc', { + const buttonLabel = i18n.translate('unifiedDataTable.grid.viewDoc', { defaultMessage: 'Toggle dialog with details', }); @@ -63,7 +64,7 @@ export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle return ( { const component = mountWithIntl( - - + ); @@ -31,32 +33,32 @@ describe('DiscoverGridFooter', function () { it('should not render anything yet when all rows shown', async () => { const component = mountWithIntl( - - - + ); expect(component.isEmptyRender()).toBe(true); }); it('should render a message for the last page', async () => { const component = mountWithIntl( - - - + ); - expect(findTestSubject(component, 'discoverTableFooter').text()).toBe( + expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe( 'Search results are limited to 500 documents. Add more search terms to narrow your search.' ); expect(findTestSubject(component, 'dscGridSampleSizeFetchMoreLink').exists()).toBe(false); @@ -66,19 +68,19 @@ describe('DiscoverGridFooter', function () { const mockLoadMore = jest.fn(); const component = mountWithIntl( - - - + ); - expect(findTestSubject(component, 'discoverTableFooter').text()).toBe( + expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe( 'Search results are limited to 500 documents.Load more' ); @@ -94,19 +96,19 @@ describe('DiscoverGridFooter', function () { const mockLoadMore = jest.fn(); const component = mountWithIntl( - - - + ); - expect(findTestSubject(component, 'discoverTableFooter').text()).toBe( + expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe( 'Search results are limited to 500 documents.Load more' ); @@ -121,17 +123,17 @@ describe('DiscoverGridFooter', function () { it('should render a message when max total limit is reached', async () => { const component = mountWithIntl( - - - + ); - expect(findTestSubject(component, 'discoverTableFooter').text()).toBe( + expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe( 'Search results are limited to 10000 documents. Add more search terms to narrow your search.' ); }); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_footer.tsx b/packages/kbn-unified-data-table/src/components/data_table_footer.tsx similarity index 75% rename from src/plugins/discover/public/components/discover_grid/discover_grid_footer.tsx rename to packages/kbn-unified-data-table/src/components/data_table_footer.tsx index 540c7102bd424..21819a023afed 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_footer.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_footer.tsx @@ -12,10 +12,11 @@ import { EuiButtonEmpty, EuiToolTip, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import { i18n } from '@kbn/i18n'; import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; -import { MAX_LOADED_GRID_ROWS } from '../../../common/constants'; -import { useDiscoverServices } from '../../hooks/use_discover_services'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import { MAX_LOADED_GRID_ROWS } from '../constants'; -export interface DiscoverGridFooterProps { +export interface UnifiedDataTableFooterProps { isLoadingMore?: boolean; rowCount: number; sampleSize: number; @@ -23,9 +24,11 @@ export interface DiscoverGridFooterProps { pageCount: number; totalHits?: number; onFetchMoreRecords?: () => void; + data: DataPublicPluginStart; + fieldFormats: FieldFormatsStart; } -export const DiscoverGridFooter: React.FC = (props) => { +export const UnifiedDataTableFooter: React.FC = (props) => { const { isLoadingMore, rowCount, @@ -34,8 +37,8 @@ export const DiscoverGridFooter: React.FC = (props) => pageCount, totalHits = 0, onFetchMoreRecords, + data, } = props; - const { data } = useDiscoverServices(); const timefilter = data.query.timefilter.timefilter; const [refreshInterval, setRefreshInterval] = useState(timefilter.getRefreshInterval()); @@ -58,15 +61,15 @@ export const DiscoverGridFooter: React.FC = (props) => return null; } - // allow to fetch more records on Discover page + // allow to fetch more records for UnifiedDataTable if (onFetchMoreRecords && typeof isLoadingMore === 'boolean') { if (rowCount <= MAX_LOADED_GRID_ROWS - sampleSize) { return ( - + = (props) => `} > - + ); } - return ; + return ; } if (rowCount < totalHits) { // show only a message for embeddable - return ; + return ; } return null; }; -interface DiscoverGridFooterContainerProps extends DiscoverGridFooterProps { +interface UnifiedDataTableFooterContainerProps extends UnifiedDataTableFooterProps { hasButton: boolean; } -const DiscoverGridFooterContainer: React.FC = ({ +const UnifiedDataTableFooterContainer: React.FC = ({ hasButton, rowCount, children, + fieldFormats, }) => { const { euiTheme } = useEuiTheme(); - const { fieldFormats } = useDiscoverServices(); const formattedRowCount = fieldFormats .getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER]) @@ -121,7 +124,7 @@ const DiscoverGridFooterContainer: React.FC = return (

    = {hasButton ? ( = /> ) : ( true); +jest.mock('@elastic/eui', () => { + const original = jest.requireActual('@elastic/eui'); + return { + ...original, + copyToClipboard: (value: string) => mockCopyToClipboard(value), + }; +}); + +import React from 'react'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { findTestSubject } from '@elastic/eui/lib/test'; +import { + FilterInBtn, + FilterOutBtn, + buildCellActions, + buildCopyValueButton, +} from './default_cell_actions'; +import { servicesMock } from '../../__mocks__/services'; +import { UnifiedDataTableContext } from '../table_context'; +import { EuiButton, EuiDataGridColumnCellActionProps } from '@elastic/eui'; +import { dataTableContextMock } from '../../__mocks__/table_context'; +import { DataViewField } from '@kbn/data-views-plugin/public'; + +describe('Default cell actions ', function () { + const CopyBtn = buildCopyValueButton( + { + Component: () => <>, + colIndex: 0, + columnId: 'extension', + } as unknown as EuiDataGridColumnCellActionProps, + servicesMock.toastNotifications, + dataTableContextMock.valueToStringConverter + ); + + it('should not show cell actions for unfilterable fields', async () => { + const cellActions = buildCellActions( + { name: 'foo', filterable: false } as DataViewField, + servicesMock.toastNotifications, + dataTableContextMock.valueToStringConverter + ); + expect(cellActions.length).toEqual(1); + expect( + cellActions[0]({ + Component: () => <>, + colIndex: 1, + columnId: 'extension', + } as unknown as EuiDataGridColumnCellActionProps).props['aria-label'] + ).toEqual(CopyBtn.props['aria-label']); + }); + + it('should show filter actions for filterable fields', async () => { + const cellActions = buildCellActions( + { name: 'foo', filterable: true } as DataViewField, + servicesMock.toastNotifications, + dataTableContextMock.valueToStringConverter, + jest.fn() + ); + expect(cellActions).toContain(FilterInBtn); + expect(cellActions).toContain(FilterOutBtn); + }); + + it('should show Copy action for _source field', async () => { + const cellActions = buildCellActions( + { name: '_source', type: '_source', filterable: false } as DataViewField, + servicesMock.toastNotifications, + dataTableContextMock.valueToStringConverter + ); + expect( + cellActions[0]({ + Component: () => <>, + colIndex: 1, + columnId: 'extension', + } as unknown as EuiDataGridColumnCellActionProps).props['aria-label'] + ).toEqual(CopyBtn.props['aria-label']); + }); + + it('triggers filter function when FilterInBtn is clicked', async () => { + const component = mountWithIntl( + + } + rowIndex={1} + colIndex={1} + columnId="extension" + isExpanded={false} + /> + + ); + const button = findTestSubject(component, 'filterForButton'); + await button.simulate('click'); + expect(dataTableContextMock.onFilter).toHaveBeenCalledWith( + dataTableContextMock.dataView.fields.getByName('extension'), + 'jpg', + '+' + ); + }); + it('triggers filter function when FilterInBtn is clicked for a non-provided value', async () => { + const component = mountWithIntl( + + } + rowIndex={0} + colIndex={1} + columnId="extension" + isExpanded={false} + /> + + ); + const button = findTestSubject(component, 'filterForButton'); + await button.simulate('click'); + expect(dataTableContextMock.onFilter).toHaveBeenCalledWith( + dataTableContextMock.dataView.fields.getByName('extension'), + undefined, + '+' + ); + }); + it('triggers filter function when FilterInBtn is clicked for an empty string value', async () => { + const component = mountWithIntl( + + } + rowIndex={4} + colIndex={1} + columnId="message" + isExpanded={false} + /> + + ); + const button = findTestSubject(component, 'filterForButton'); + await button.simulate('click'); + expect(dataTableContextMock.onFilter).toHaveBeenCalledWith( + dataTableContextMock.dataView.fields.getByName('message'), + '', + '+' + ); + }); + it('triggers filter function when FilterOutBtn is clicked', async () => { + const component = mountWithIntl( + + } + rowIndex={1} + colIndex={1} + columnId="extension" + isExpanded={false} + /> + + ); + const button = findTestSubject(component, 'filterOutButton'); + await button.simulate('click'); + expect(dataTableContextMock.onFilter).toHaveBeenCalledWith( + dataTableContextMock.dataView.fields.getByName('extension'), + 'jpg', + '-' + ); + }); + it('triggers clipboard copy when CopyBtn is clicked', async () => { + const component = mountWithIntl( + + {buildCopyValueButton( + { + Component: (props: any) => , + colIndex: 1, + rowIndex: 1, + columnId: 'extension', + } as unknown as EuiDataGridColumnCellActionProps, + servicesMock.toastNotifications, + dataTableContextMock.valueToStringConverter + )} + + ); + const button = findTestSubject(component, 'copyClipboardButton'); + await button.simulate('click'); + expect(mockCopyToClipboard).toHaveBeenCalledWith('jpg'); + }); +}); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_cell_actions.tsx b/packages/kbn-unified-data-table/src/components/default_cell_actions.tsx similarity index 59% rename from src/plugins/discover/public/components/discover_grid/discover_grid_cell_actions.tsx rename to packages/kbn-unified-data-table/src/components/default_cell_actions.tsx index 59cd130277f90..6005d75ea6632 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_cell_actions.tsx +++ b/packages/kbn-unified-data-table/src/components/default_cell_actions.tsx @@ -9,14 +9,15 @@ import React, { useContext } from 'react'; import { EuiDataGridColumnCellActionProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { DataViewField } from '@kbn/data-views-plugin/public'; -import { DocViewFilterFn } from '../../services/doc_views/doc_views_types'; -import { DiscoverGridContext, GridContext } from './discover_grid_context'; -import { useDiscoverServices } from '../../hooks/use_discover_services'; -import { copyValueToClipboard } from '../../utils/copy_value_to_clipboard'; +import type { DataViewField } from '@kbn/data-views-plugin/public'; +import { ToastsStart } from '@kbn/core/public'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import { UnifiedDataTableContext, DataTableContext } from '../table_context'; +import { copyValueToClipboard } from '../utils/copy_value_to_clipboard'; +import { ValueToStringConverter } from '../types'; function onFilterCell( - context: GridContext, + context: DataTableContext, rowIndex: EuiDataGridColumnCellActionProps['rowIndex'], columnId: EuiDataGridColumnCellActionProps['columnId'], mode: '+' | '-' @@ -35,8 +36,8 @@ export const FilterInBtn = ({ rowIndex, columnId, }: EuiDataGridColumnCellActionProps) => { - const context = useContext(DiscoverGridContext); - const buttonTitle = i18n.translate('discover.grid.filterForAria', { + const context = useContext(UnifiedDataTableContext); + const buttonTitle = i18n.translate('unifiedDataTable.grid.filterForAria', { defaultMessage: 'Filter for this {value}', values: { value: columnId }, }); @@ -51,7 +52,7 @@ export const FilterInBtn = ({ title={buttonTitle} data-test-subj="filterForButton" > - {i18n.translate('discover.grid.filterFor', { + {i18n.translate('unifiedDataTable.grid.filterFor', { defaultMessage: 'Filter for', })} @@ -63,8 +64,8 @@ export const FilterOutBtn = ({ rowIndex, columnId, }: EuiDataGridColumnCellActionProps) => { - const context = useContext(DiscoverGridContext); - const buttonTitle = i18n.translate('discover.grid.filterOutAria', { + const context = useContext(UnifiedDataTableContext); + const buttonTitle = i18n.translate('unifiedDataTable.grid.filterOutAria', { defaultMessage: 'Filter out this {value}', values: { value: columnId }, }); @@ -79,18 +80,19 @@ export const FilterOutBtn = ({ title={buttonTitle} data-test-subj="filterOutButton" > - {i18n.translate('discover.grid.filterOut', { + {i18n.translate('unifiedDataTable.grid.filterOut', { defaultMessage: 'Filter out', })} ); }; -export const CopyBtn = ({ Component, rowIndex, columnId }: EuiDataGridColumnCellActionProps) => { - const { valueToStringConverter } = useContext(DiscoverGridContext); - const { toastNotifications } = useDiscoverServices(); - - const buttonTitle = i18n.translate('discover.grid.copyClipboardButtonTitle', { +export function buildCopyValueButton( + { Component, rowIndex, columnId }: EuiDataGridColumnCellActionProps, + toastNotifications: ToastsStart, + valueToStringConverter: ValueToStringConverter +) { + const buttonTitle = i18n.translate('unifiedDataTable.grid.copyClipboardButtonTitle', { defaultMessage: 'Copy value of {column}', values: { column: columnId }, }); @@ -101,8 +103,8 @@ export const CopyBtn = ({ Component, rowIndex, columnId }: EuiDataGridColumnCell copyValueToClipboard({ rowIndex, columnId, - toastNotifications, valueToStringConverter, + toastNotifications, }); }} iconType="copyClipboard" @@ -110,13 +112,26 @@ export const CopyBtn = ({ Component, rowIndex, columnId }: EuiDataGridColumnCell title={buttonTitle} data-test-subj="copyClipboardButton" > - {i18n.translate('discover.grid.copyCellValueButton', { + {i18n.translate('unifiedDataTable.grid.copyCellValueButton', { defaultMessage: 'Copy value', })} ); -}; +} -export function buildCellActions(field: DataViewField, onFilter?: DocViewFilterFn) { - return [...(onFilter && field.filterable ? [FilterInBtn, FilterOutBtn] : []), CopyBtn]; +export function buildCellActions( + field: DataViewField, + toastNotifications: ToastsStart, + valueToStringConverter: ValueToStringConverter, + onFilter?: DocViewFilterFn +) { + return [ + ...(onFilter && field.filterable ? [FilterInBtn, FilterOutBtn] : []), + ({ Component, rowIndex, columnId }: EuiDataGridColumnCellActionProps) => + buildCopyValueButton( + { Component, rowIndex, columnId } as EuiDataGridColumnCellActionProps, + toastNotifications, + valueToStringConverter + ), + ]; } diff --git a/src/plugins/discover/public/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap b/packages/kbn-unified-data-table/src/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap similarity index 100% rename from src/plugins/discover/public/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap rename to packages/kbn-unified-data-table/src/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap diff --git a/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.scss b/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.scss new file mode 100644 index 0000000000000..a07f7ccac408d --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.scss @@ -0,0 +1,3 @@ +.unifiedDataTableJsonEditor { + width: 100%; +} diff --git a/src/plugins/discover/public/components/json_code_editor/json_code_editor.test.tsx b/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.test.tsx similarity index 92% rename from src/plugins/discover/public/components/json_code_editor/json_code_editor.test.tsx rename to packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.test.tsx index 9ec60410b591e..e1ec1373f8657 100644 --- a/src/plugins/discover/public/components/json_code_editor/json_code_editor.test.tsx +++ b/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { JsonCodeEditor } from './json_code_editor'; +import JsonCodeEditor from './json_code_editor'; it('returns the `JsonCodeEditor` component', () => { const value = { diff --git a/src/plugins/discover/public/components/json_code_editor/json_code_editor.tsx b/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.tsx similarity index 78% rename from src/plugins/discover/public/components/json_code_editor/json_code_editor.tsx rename to packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.tsx index 426a180d37957..d08e35eb6d4bf 100644 --- a/src/plugins/discover/public/components/json_code_editor/json_code_editor.tsx +++ b/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.tsx @@ -11,14 +11,21 @@ import './json_code_editor.scss'; import React from 'react'; import { JsonCodeEditorCommon } from './json_code_editor_common'; -interface JsonCodeEditorProps { +export interface JsonCodeEditorProps { json: Record; width?: string | number; height?: string | number; hasLineNumbers?: boolean; } -export const JsonCodeEditor = ({ json, width, height, hasLineNumbers }: JsonCodeEditorProps) => { +// Required for usage in React.lazy +// eslint-disable-next-line import/no-default-export +export default function JsonCodeEditor({ + json, + width, + height, + hasLineNumbers, +}: JsonCodeEditorProps) { const jsonValue = JSON.stringify(json, null, 2); return ( @@ -31,4 +38,4 @@ export const JsonCodeEditor = ({ json, width, height, hasLineNumbers }: JsonCode hideCopyButton={true} /> ); -}; +} diff --git a/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor_common.tsx b/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor_common.tsx new file mode 100644 index 0000000000000..079a98c305459 --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor_common.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import './json_code_editor.scss'; + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { monaco, XJsonLang } from '@kbn/monaco'; +import { EuiButtonEmpty, EuiCopy, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { CodeEditor } from '@kbn/code-editor'; +const codeEditorAriaLabel = i18n.translate('unifiedDataTable.json.codeEditorAriaLabel', { + defaultMessage: 'Read only JSON view of an elasticsearch document', +}); +const copyToClipboardLabel = i18n.translate('unifiedDataTable.json.copyToClipboardLabel', { + defaultMessage: 'Copy to clipboard', +}); + +interface JsonCodeEditorCommonProps { + jsonValue: string; + onEditorDidMount: (editor: monaco.editor.IStandaloneCodeEditor) => void; + width?: string | number; + height?: string | number; + hasLineNumbers?: boolean; + hideCopyButton?: boolean; +} + +export const JsonCodeEditorCommon = ({ + jsonValue, + width, + height, + hasLineNumbers, + onEditorDidMount, + hideCopyButton, +}: JsonCodeEditorCommonProps) => { + if (jsonValue === '') { + return null; + } + + const codeEditor = ( + + ); + if (hideCopyButton) { + return codeEditor; + } + return ( + + + +

    + + {(copy) => ( + + {copyToClipboardLabel} + + )} + +
    + + {codeEditor} + + ); +}; + +export const JSONCodeEditorCommonMemoized = React.memo((props: JsonCodeEditorCommonProps) => { + return ; +}); diff --git a/src/plugins/discover/public/components/discover_grid/constants.ts b/packages/kbn-unified-data-table/src/constants.ts similarity index 81% rename from src/plugins/discover/public/components/discover_grid/constants.ts rename to packages/kbn-unified-data-table/src/constants.ts index 8f7c40e33b957..1fb391ddc7f70 100644 --- a/src/plugins/discover/public/components/discover_grid/constants.ts +++ b/packages/kbn-unified-data-table/src/constants.ts @@ -5,11 +5,17 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - import { EuiDataGridStyle } from '@elastic/eui'; -// data types +export const DEFAULT_ROWS_PER_PAGE = 100; +export const MAX_LOADED_GRID_ROWS = 10000; + +export const ROWS_PER_PAGE_OPTIONS = [10, 25, 50, DEFAULT_ROWS_PER_PAGE, 250, 500]; + +export const defaultMonacoEditorWidth = 370; +export const defaultTimeColumnWidth = 210; export const kibanaJSON = 'kibana-json'; + export const GRID_STYLE = { border: 'all', fontSize: 's', @@ -17,12 +23,9 @@ export const GRID_STYLE = { rowHover: 'none', } as EuiDataGridStyle; -export const defaultTimeColumnWidth = 210; export const toolbarVisibility = { showColumnSelector: { allowHide: false, allowReorder: true, }, }; - -export const defaultMonacoEditorWidth = 370; diff --git a/src/plugins/discover/public/hooks/use_data_grid_columns.test.tsx b/packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.test.tsx similarity index 94% rename from src/plugins/discover/public/hooks/use_data_grid_columns.test.tsx rename to packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.test.tsx index 4a1874ec8e940..e0afdab4ff043 100644 --- a/src/plugins/discover/public/hooks/use_data_grid_columns.test.tsx +++ b/packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.test.tsx @@ -9,8 +9,8 @@ import { renderHook } from '@testing-library/react-hooks'; import { useColumns } from './use_data_grid_columns'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { configMock } from '../__mocks__/config'; -import { dataViewsMock } from '../__mocks__/data_views'; +import { configMock } from '../../__mocks__/config'; +import { dataViewsMock } from '../../__mocks__/data_views'; import { Capabilities } from '@kbn/core/types'; describe('useColumns', () => { diff --git a/src/plugins/discover/public/hooks/use_data_grid_columns.ts b/packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.ts similarity index 74% rename from src/plugins/discover/public/hooks/use_data_grid_columns.ts rename to packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.ts index 22fc8e9836888..088f7b0491c69 100644 --- a/src/plugins/discover/public/hooks/use_data_grid_columns.ts +++ b/packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.ts @@ -9,32 +9,30 @@ import { useEffect, useMemo, useState } from 'react'; import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'; -import { Capabilities, IUiSettingsClient } from '@kbn/core/public'; +import { Capabilities } from '@kbn/core/public'; import { isEqual } from 'lodash'; -import { DiscoverAppStateContainer } from '../application/main/services/discover_app_state_container'; -import { GetStateReturn as ContextGetStateReturn } from '../application/context/services/context_state'; -import { getStateColumnActions } from '../components/doc_table/actions/columns'; +import { getStateColumnActions } from '../components/actions/columns'; interface UseColumnsProps { capabilities: Capabilities; - config: IUiSettingsClient; dataView: DataView; dataViews: DataViewsContract; useNewFieldsApi: boolean; - setAppState: DiscoverAppStateContainer['update'] | ContextGetStateReturn['setAppState']; + setAppState: (state: { columns: string[]; sort?: string[][] }) => void; columns?: string[]; sort?: string[][]; + defaultOrder?: string; } export const useColumns = ({ capabilities, - config, dataView, dataViews, setAppState, useNewFieldsApi, columns, sort, + defaultOrder = 'desc', }: UseColumnsProps) => { const [usedColumns, setUsedColumns] = useState(getColumns(columns, useNewFieldsApi)); useEffect(() => { @@ -48,15 +46,24 @@ export const useColumns = ({ () => getStateColumnActions({ capabilities, - config, dataView, dataViews, setAppState, useNewFieldsApi, columns: usedColumns, sort, + defaultOrder, }), - [capabilities, config, dataView, dataViews, setAppState, sort, useNewFieldsApi, usedColumns] + [ + capabilities, + dataView, + dataViews, + defaultOrder, + setAppState, + sort, + useNewFieldsApi, + usedColumns, + ] ); return { diff --git a/packages/kbn-unified-data-table/src/hooks/use_row_heights_options.test.tsx b/packages/kbn-unified-data-table/src/hooks/use_row_heights_options.test.tsx new file mode 100644 index 0000000000000..2da08c178720a --- /dev/null +++ b/packages/kbn-unified-data-table/src/hooks/use_row_heights_options.test.tsx @@ -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 { renderHook } from '@testing-library/react-hooks'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { LocalStorageMock } from '../../__mocks__/local_storage_mock'; +import { useRowHeightsOptions } from './use_row_heights_options'; + +const CONFIG_ROW_HEIGHT = 3; + +describe('useRowHeightsOptions', () => { + test('should apply rowHeight from savedSearch', () => { + const { result } = renderHook(() => { + return useRowHeightsOptions({ + rowHeightState: 2, + storage: new LocalStorageMock({}) as unknown as Storage, + consumer: 'discover', + }); + }); + + expect(result.current.defaultHeight).toEqual({ lineCount: 2 }); + }); + + test('should apply rowHeight from local storage', () => { + const { result } = renderHook(() => { + return useRowHeightsOptions({ + storage: new LocalStorageMock({ + ['discover:dataGridRowHeight']: { + previousRowHeight: 5, + previousConfigRowHeight: 3, + }, + }) as unknown as Storage, + consumer: 'discover', + }); + }); + + expect(result.current.defaultHeight).toEqual({ lineCount: 5 }); + }); + + test('should apply rowHeight from configRowHeight', () => { + const { result } = renderHook(() => { + return useRowHeightsOptions({ + consumer: 'discover', + configRowHeight: 3, + storage: new LocalStorageMock({}) as unknown as Storage, + }); + }); + + expect(result.current.defaultHeight).toEqual({ + lineCount: CONFIG_ROW_HEIGHT, + }); + }); + + test('should apply rowHeight from uiSettings instead of local storage value, since uiSettings has been changed', () => { + const { result } = renderHook(() => { + return useRowHeightsOptions({ + storage: new LocalStorageMock({ + ['discover:dataGridRowHeight']: { + previousRowHeight: 4, + // different from uiSettings (config), now user changed it to 3, but prev was 4 + previousConfigRowHeight: 4, + }, + }) as unknown as Storage, + consumer: 'discover', + }); + }); + + expect(result.current.defaultHeight).toEqual({ + lineCount: CONFIG_ROW_HEIGHT, + }); + }); +}); diff --git a/src/plugins/discover/public/hooks/use_row_heights_options.ts b/packages/kbn-unified-data-table/src/hooks/use_row_heights_options.ts similarity index 84% rename from src/plugins/discover/public/hooks/use_row_heights_options.ts rename to packages/kbn-unified-data-table/src/hooks/use_row_heights_options.ts index a9ef67ace530b..9d460c8ea2ba9 100644 --- a/src/plugins/discover/public/hooks/use_row_heights_options.ts +++ b/packages/kbn-unified-data-table/src/hooks/use_row_heights_options.ts @@ -7,10 +7,9 @@ */ import type { EuiDataGridRowHeightOption, EuiDataGridRowHeightsOptions } from '@elastic/eui'; +import type { Storage } from '@kbn/kibana-utils-plugin/public'; import { useMemo } from 'react'; -import { ROW_HEIGHT_OPTION } from '@kbn/discover-utils'; import { isValidRowHeight } from '../utils/validate_row_height'; -import { useDiscoverServices } from './use_discover_services'; import { DataGridOptionsRecord, getStoredRowHeight, @@ -20,6 +19,9 @@ import { interface UseRowHeightProps { rowHeightState?: number; onUpdateRowHeight?: (rowHeight: number) => void; + storage: Storage; + configRowHeight?: number; + consumer: string; } /** @@ -30,6 +32,7 @@ interface UseRowHeightProps { */ const SINGLE_ROW_HEIGHT_OPTION = 0; const AUTO_ROW_HEIGHT_OPTION = -1; +const DEFAULT_ROW_HEIGHT_OPTION = 3; /** * Converts rowHeight of EuiDataGrid to rowHeight number (-1 to 20) @@ -57,12 +60,15 @@ const deserializeRowHeight = (number: number): EuiDataGridRowHeightOption | unde return { lineCount: number }; // custom }; -export const useRowHeightsOptions = ({ rowHeightState, onUpdateRowHeight }: UseRowHeightProps) => { - const { storage, uiSettings } = useDiscoverServices(); - +export const useRowHeightsOptions = ({ + rowHeightState, + onUpdateRowHeight, + storage, + configRowHeight = DEFAULT_ROW_HEIGHT_OPTION, + consumer, +}: UseRowHeightProps) => { return useMemo((): EuiDataGridRowHeightsOptions => { - const rowHeightFromLS = getStoredRowHeight(storage); - const configRowHeight = uiSettings.get(ROW_HEIGHT_OPTION); + const rowHeightFromLS = getStoredRowHeight(storage, consumer); const configHasNotChanged = ( localStorageRecord: DataGridOptionsRecord | null @@ -83,9 +89,9 @@ export const useRowHeightsOptions = ({ rowHeightState, onUpdateRowHeight }: UseR lineHeight: '1.6em', onChange: ({ defaultHeight: newRowHeight }: EuiDataGridRowHeightsOptions) => { const newSerializedRowHeight = serializeRowHeight(newRowHeight); - updateStoredRowHeight(newSerializedRowHeight, configRowHeight, storage); + updateStoredRowHeight(newSerializedRowHeight, configRowHeight, storage, consumer); onUpdateRowHeight?.(newSerializedRowHeight); }, }; - }, [rowHeightState, uiSettings, storage, onUpdateRowHeight]); + }, [storage, consumer, rowHeightState, configRowHeight, onUpdateRowHeight]); }; diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_context.tsx b/packages/kbn-unified-data-table/src/table_context.tsx similarity index 70% rename from src/plugins/discover/public/components/discover_grid/discover_grid_context.tsx rename to packages/kbn-unified-data-table/src/table_context.tsx index 8ec4689a00178..2a1d4656d4a65 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_context.tsx +++ b/packages/kbn-unified-data-table/src/table_context.tsx @@ -9,10 +9,10 @@ import React from 'react'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { DataTableRecord } from '@kbn/discover-utils/types'; -import type { DocViewFilterFn } from '../../services/doc_views/doc_views_types'; -import type { ValueToStringConverter } from '../../types'; +import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import type { ValueToStringConverter } from './types'; -export interface GridContext { +export interface DataTableContext { expanded?: DataTableRecord | undefined; setExpanded?: (hit?: DataTableRecord) => void; rows: DataTableRecord[]; @@ -22,8 +22,9 @@ export interface GridContext { selectedDocs: string[]; setSelectedDocs: (selected: string[]) => void; valueToStringConverter: ValueToStringConverter; + componentsTourSteps?: Record; } -const defaultContext = {} as unknown as GridContext; +const defaultContext = {} as unknown as DataTableContext; -export const DiscoverGridContext = React.createContext(defaultContext); +export const UnifiedDataTableContext = React.createContext(defaultContext); diff --git a/src/plugins/discover/public/types.ts b/packages/kbn-unified-data-table/src/types.ts similarity index 57% rename from src/plugins/discover/public/types.ts rename to packages/kbn-unified-data-table/src/types.ts index 051892902239d..79ca4e721e910 100644 --- a/src/plugins/discover/public/types.ts +++ b/packages/kbn-unified-data-table/src/types.ts @@ -6,18 +6,19 @@ * Side Public License, v 1. */ -import type { DatatableColumn } from '@kbn/expressions-plugin/common'; -import type { DataTableRecord } from '@kbn/discover-utils/types'; -import type { SearchResponseInterceptedWarning } from '@kbn/search-response-warnings'; +/** + * User configurable state of data grid, persisted in saved search + */ +export interface UnifiedDataTableSettings { + columns?: Record; +} + +export interface UnifiedDataTableSettingsColumn { + width?: number; +} export type ValueToStringConverter = ( rowIndex: number, columnId: string, options?: { compatibleWithCSV?: boolean } ) => { formattedString: string; withFormula: boolean }; - -export interface RecordsFetchResponse { - records: DataTableRecord[]; - textBasedQueryColumns?: DatatableColumn[]; - interceptedWarnings?: SearchResponseInterceptedWarning[]; -} diff --git a/src/plugins/discover/public/utils/columns.test.ts b/packages/kbn-unified-data-table/src/utils/columns.test.ts similarity index 95% rename from src/plugins/discover/public/utils/columns.test.ts rename to packages/kbn-unified-data-table/src/utils/columns.test.ts index 5ef7d8fea450f..36a8b60a6bc68 100644 --- a/src/plugins/discover/public/utils/columns.test.ts +++ b/packages/kbn-unified-data-table/src/utils/columns.test.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; import { getDisplayedColumns } from './columns'; -import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; describe('getDisplayedColumns', () => { diff --git a/src/plugins/discover/public/utils/columns.ts b/packages/kbn-unified-data-table/src/utils/columns.ts similarity index 94% rename from src/plugins/discover/public/utils/columns.ts rename to packages/kbn-unified-data-table/src/utils/columns.ts index 49e234b11decc..f2a72f0a8b650 100644 --- a/src/plugins/discover/public/utils/columns.ts +++ b/packages/kbn-unified-data-table/src/utils/columns.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { DataView } from '@kbn/data-views-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; // We store this outside the function as a constant, so we're not creating a new array every time // the function is returning this. A changing array might cause the data grid to think it got diff --git a/src/plugins/discover/public/utils/convert_value_to_string.test.tsx b/packages/kbn-unified-data-table/src/utils/convert_value_to_string.test.tsx similarity index 67% rename from src/plugins/discover/public/utils/convert_value_to_string.test.tsx rename to packages/kbn-unified-data-table/src/utils/convert_value_to_string.test.tsx index dd81ad621f182..aa8ba719c5ba2 100644 --- a/src/plugins/discover/public/utils/convert_value_to_string.test.tsx +++ b/packages/kbn-unified-data-table/src/utils/convert_value_to_string.test.tsx @@ -6,16 +6,16 @@ * Side Public License, v 1. */ -import { discoverGridContextComplexMock, discoverGridContextMock } from '../__mocks__/grid_context'; -import { discoverServiceMock } from '../__mocks__/services'; +import { dataTableContextComplexMock, dataTableContextMock } from '../../__mocks__/table_context'; +import { servicesMock } from '../../__mocks__/services'; import { convertValueToString, convertNameToString } from './convert_value_to_string'; describe('convertValueToString', () => { it('should convert a keyword value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'keyword_key', rowIndex: 0, options: { @@ -28,9 +28,9 @@ describe('convertValueToString', () => { it('should convert a text value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'text_message', rowIndex: 0, options: { @@ -43,9 +43,9 @@ describe('convertValueToString', () => { it('should convert a text value to text (not for CSV)', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'text_message', rowIndex: 0, options: { @@ -58,9 +58,9 @@ describe('convertValueToString', () => { it('should convert a multiline text value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'text_message', rowIndex: 1, options: { @@ -74,9 +74,9 @@ describe('convertValueToString', () => { it('should convert a number value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'number_price', rowIndex: 0, options: { @@ -89,9 +89,9 @@ describe('convertValueToString', () => { it('should convert a date value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'date', rowIndex: 0, options: { @@ -104,9 +104,9 @@ describe('convertValueToString', () => { it('should convert a date nanos value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'date_nanos', rowIndex: 0, options: { @@ -119,9 +119,9 @@ describe('convertValueToString', () => { it('should convert a date nanos value to text (not for CSV)', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'date_nanos', rowIndex: 0, options: { @@ -134,9 +134,9 @@ describe('convertValueToString', () => { it('should convert a boolean value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'bool_enabled', rowIndex: 0, options: { @@ -149,9 +149,9 @@ describe('convertValueToString', () => { it('should convert a binary value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'binary_blob', rowIndex: 0, options: { @@ -164,9 +164,9 @@ describe('convertValueToString', () => { it('should convert a binary value to text (not for CSV)', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'binary_blob', rowIndex: 0, options: { @@ -179,9 +179,9 @@ describe('convertValueToString', () => { it('should convert an object value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'object_user.first', rowIndex: 0, options: { @@ -194,9 +194,9 @@ describe('convertValueToString', () => { it('should convert a nested value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'nested_user', rowIndex: 0, options: { @@ -211,9 +211,9 @@ describe('convertValueToString', () => { it('should convert a flattened value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'flattened_labels', rowIndex: 0, options: { @@ -226,9 +226,9 @@ describe('convertValueToString', () => { it('should convert a range value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'range_time_frame', rowIndex: 0, options: { @@ -243,9 +243,9 @@ describe('convertValueToString', () => { it('should convert a rank features value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'rank_features', rowIndex: 0, options: { @@ -258,9 +258,9 @@ describe('convertValueToString', () => { it('should convert a histogram value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'histogram', rowIndex: 0, options: { @@ -273,9 +273,9 @@ describe('convertValueToString', () => { it('should convert a IP value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'ip_addr', rowIndex: 0, options: { @@ -288,9 +288,9 @@ describe('convertValueToString', () => { it('should convert a IP value to text (not for CSV)', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'ip_addr', rowIndex: 0, options: { @@ -303,9 +303,9 @@ describe('convertValueToString', () => { it('should convert a version value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'version', rowIndex: 0, options: { @@ -318,9 +318,9 @@ describe('convertValueToString', () => { it('should convert a version value to text (not for CSV)', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'version', rowIndex: 0, options: { @@ -333,9 +333,9 @@ describe('convertValueToString', () => { it('should convert a vector value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'vector', rowIndex: 0, options: { @@ -348,9 +348,9 @@ describe('convertValueToString', () => { it('should convert a geo point value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'geo_point', rowIndex: 0, options: { @@ -363,9 +363,9 @@ describe('convertValueToString', () => { it('should convert a geo point object value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'geo_point', rowIndex: 1, options: { @@ -378,9 +378,9 @@ describe('convertValueToString', () => { it('should convert an array value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'array_tags', rowIndex: 0, options: { @@ -393,9 +393,9 @@ describe('convertValueToString', () => { it('should convert a shape value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'geometry', rowIndex: 0, options: { @@ -410,9 +410,9 @@ describe('convertValueToString', () => { it('should convert a runtime value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'runtime_number', rowIndex: 0, options: { @@ -425,9 +425,9 @@ describe('convertValueToString', () => { it('should convert a scripted value to text', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'scripted_string', rowIndex: 0, options: { @@ -440,9 +440,9 @@ describe('convertValueToString', () => { it('should convert a scripted value to text (not for CSV)', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'scripted_string', rowIndex: 0, options: { @@ -455,9 +455,9 @@ describe('convertValueToString', () => { it('should return an empty string and not fail', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'unknown', rowIndex: 0, options: { @@ -470,9 +470,9 @@ describe('convertValueToString', () => { it('should return an empty string when rowIndex is out of range', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'unknown', rowIndex: -1, options: { @@ -485,9 +485,9 @@ describe('convertValueToString', () => { it('should return _source value', () => { const result = convertValueToString({ - rows: discoverGridContextMock.rows, - dataView: discoverGridContextMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextMock.rows, + dataView: dataTableContextMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: '_source', rowIndex: 0, options: { @@ -508,9 +508,9 @@ describe('convertValueToString', () => { it('should return a formatted _source value', () => { const result = convertValueToString({ - rows: discoverGridContextMock.rows, - dataView: discoverGridContextMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextMock.rows, + dataView: dataTableContextMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: '_source', rowIndex: 0, options: { @@ -525,9 +525,9 @@ describe('convertValueToString', () => { it('should escape formula', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'array_tags', rowIndex: 1, options: { @@ -539,9 +539,9 @@ describe('convertValueToString', () => { expect(result.withFormula).toBe(true); const result2 = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'scripted_string', rowIndex: 1, options: { @@ -555,9 +555,9 @@ describe('convertValueToString', () => { it('should not escape formulas when not for CSV', () => { const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, columnId: 'array_tags', rowIndex: 1, options: { diff --git a/src/plugins/discover/public/utils/convert_value_to_string.ts b/packages/kbn-unified-data-table/src/utils/convert_value_to_string.ts similarity index 95% rename from src/plugins/discover/public/utils/convert_value_to_string.ts rename to packages/kbn-unified-data-table/src/utils/convert_value_to_string.ts index 605c7912b17f1..486ed5574dbf2 100644 --- a/src/plugins/discover/public/utils/convert_value_to_string.ts +++ b/packages/kbn-unified-data-table/src/utils/convert_value_to_string.ts @@ -6,9 +6,9 @@ * Side Public License, v 1. */ -import { DataView } from '@kbn/data-views-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; import { cellHasFormulas, createEscapeValue } from '@kbn/data-plugin/common'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { DataTableRecord } from '@kbn/discover-utils/types'; import { formatFieldValue } from '@kbn/discover-utils'; diff --git a/src/plugins/discover/public/utils/copy_value_to_clipboard.test.tsx b/packages/kbn-unified-data-table/src/utils/copy_value_to_clipboard.test.tsx similarity index 77% rename from src/plugins/discover/public/utils/copy_value_to_clipboard.test.tsx rename to packages/kbn-unified-data-table/src/utils/copy_value_to_clipboard.test.tsx index 595b7601b6f65..7ff5c9b3f19b6 100644 --- a/src/plugins/discover/public/utils/copy_value_to_clipboard.test.tsx +++ b/packages/kbn-unified-data-table/src/utils/copy_value_to_clipboard.test.tsx @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import { discoverGridContextComplexMock } from '../__mocks__/grid_context'; -import { discoverServiceMock } from '../__mocks__/services'; +import { dataTableContextComplexMock } from '../../__mocks__/table_context'; +import { servicesMock } from '../../__mocks__/services'; import { copyValueToClipboard, copyColumnNameToClipboard, @@ -22,9 +22,9 @@ const warn = jest.spyOn(console, 'warn').mockImplementation(() => {}); describe('copyValueToClipboard', () => { const valueToStringConverter: ValueToStringConverter = (rowIndex, columnId, options) => convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, rowIndex, columnId, options, @@ -39,6 +39,10 @@ describe('copyValueToClipboard', () => { }, writable: true, }); + Object.defineProperty(window, 'sessionStorage', { + value: { clear: jest.fn() }, + writable: true, + }); }); afterAll(() => { @@ -50,7 +54,7 @@ describe('copyValueToClipboard', () => { it('should copy a value to clipboard', () => { execCommandMock.mockImplementationOnce(() => true); const result = copyValueToClipboard({ - toastNotifications: discoverServiceMock.toastNotifications, + toastNotifications: servicesMock.toastNotifications, columnId: 'keyword_key', rowIndex: 0, valueToStringConverter, @@ -59,7 +63,7 @@ describe('copyValueToClipboard', () => { expect(result).toBe('abcd1'); expect(execCommandMock).toHaveBeenCalledWith('copy'); expect(warn).not.toHaveBeenCalled(); - expect(discoverServiceMock.toastNotifications.addInfo).toHaveBeenCalledWith({ + expect(servicesMock.toastNotifications.addInfo).toHaveBeenCalledWith({ title: 'Copied to clipboard', }); }); @@ -68,7 +72,7 @@ describe('copyValueToClipboard', () => { execCommandMock.mockImplementationOnce(() => false); const result = copyValueToClipboard({ - toastNotifications: discoverServiceMock.toastNotifications, + toastNotifications: servicesMock.toastNotifications, columnId: 'keyword_key', rowIndex: 0, valueToStringConverter, @@ -77,7 +81,7 @@ describe('copyValueToClipboard', () => { expect(result).toBe(null); expect(execCommandMock).toHaveBeenCalledWith('copy'); expect(warn).toHaveBeenCalledWith('Unable to copy to clipboard.'); - expect(discoverServiceMock.toastNotifications.addWarning).toHaveBeenCalledWith({ + expect(servicesMock.toastNotifications.addWarning).toHaveBeenCalledWith({ title: 'Unable to copy to clipboard in this browser', }); }); @@ -85,13 +89,13 @@ describe('copyValueToClipboard', () => { it('should copy a column name to clipboard', () => { execCommandMock.mockImplementationOnce(() => true); const result = copyColumnNameToClipboard({ - toastNotifications: discoverServiceMock.toastNotifications, + toastNotifications: servicesMock.toastNotifications, columnDisplayName: 'text_message', }); expect(result).toBe('"text_message"'); expect(execCommandMock).toHaveBeenCalledWith('copy'); - expect(discoverServiceMock.toastNotifications.addInfo).toHaveBeenCalledWith({ + expect(servicesMock.toastNotifications.addInfo).toHaveBeenCalledWith({ title: 'Copied to clipboard', }); }); @@ -99,14 +103,14 @@ describe('copyValueToClipboard', () => { it('should inform when copy a column name to clipboard failed', () => { execCommandMock.mockImplementationOnce(() => false); const result = copyColumnNameToClipboard({ - toastNotifications: discoverServiceMock.toastNotifications, + toastNotifications: servicesMock.toastNotifications, columnDisplayName: 'text_message', }); expect(result).toBe(null); expect(execCommandMock).toHaveBeenCalledWith('copy'); expect(warn).toHaveBeenCalledWith('Unable to copy to clipboard.'); - expect(discoverServiceMock.toastNotifications.addWarning).toHaveBeenCalledWith({ + expect(servicesMock.toastNotifications.addWarning).toHaveBeenCalledWith({ title: 'Unable to copy to clipboard in this browser', }); }); @@ -115,7 +119,7 @@ describe('copyValueToClipboard', () => { execCommandMock.mockImplementationOnce(() => true); const result = await copyColumnValuesToClipboard({ - toastNotifications: discoverServiceMock.toastNotifications, + toastNotifications: servicesMock.toastNotifications, columnId: 'bool_enabled', columnDisplayName: 'custom_bool_enabled', rowsCount: 2, @@ -126,7 +130,7 @@ describe('copyValueToClipboard', () => { expect(global.window.navigator.clipboard.writeText).toHaveBeenCalledWith( '"custom_bool_enabled"\nfalse\ntrue' ); - expect(discoverServiceMock.toastNotifications.addInfo).toHaveBeenCalledWith({ + expect(servicesMock.toastNotifications.addInfo).toHaveBeenCalledWith({ title: 'Values of "custom_bool_enabled" column copied to clipboard', }); }); @@ -134,7 +138,7 @@ describe('copyValueToClipboard', () => { it('should copy column values to clipboard with a warning', async () => { execCommandMock.mockImplementationOnce(() => true); const result = await copyColumnValuesToClipboard({ - toastNotifications: discoverServiceMock.toastNotifications, + toastNotifications: servicesMock.toastNotifications, columnId: 'scripted_string', columnDisplayName: 'custom_scripted_string', rowsCount: 2, @@ -142,7 +146,7 @@ describe('copyValueToClipboard', () => { }); expect(result).toBe('"custom_scripted_string"\n"hi there"\n"\'=1+2"";=1+2"'); - expect(discoverServiceMock.toastNotifications.addWarning).toHaveBeenCalledWith({ + expect(servicesMock.toastNotifications.addWarning).toHaveBeenCalledWith({ title: 'Values of "custom_scripted_string" column copied to clipboard', text: 'Values may contain formulas that are escaped.', }); diff --git a/src/plugins/discover/public/utils/copy_value_to_clipboard.ts b/packages/kbn-unified-data-table/src/utils/copy_value_to_clipboard.ts similarity index 89% rename from src/plugins/discover/public/utils/copy_value_to_clipboard.ts rename to packages/kbn-unified-data-table/src/utils/copy_value_to_clipboard.ts index c700fa748f335..2e9620b42728b 100644 --- a/src/plugins/discover/public/utils/copy_value_to_clipboard.ts +++ b/packages/kbn-unified-data-table/src/utils/copy_value_to_clipboard.ts @@ -13,12 +13,12 @@ import type { ValueToStringConverter } from '../types'; import { convertNameToString } from './convert_value_to_string'; const WARNING_FOR_FORMULAS = i18n.translate( - 'discover.grid.copyEscapedValueWithFormulasToClipboardWarningText', + 'unifiedDataTable.copyEscapedValueWithFormulasToClipboardWarningText', { defaultMessage: 'Values may contain formulas that are escaped.', } ); -const COPY_FAILED_ERROR_MESSAGE = i18n.translate('discover.grid.copyFailedErrorText', { +const COPY_FAILED_ERROR_MESSAGE = i18n.translate('unifiedDataTable.copyFailedErrorText', { defaultMessage: 'Unable to copy to clipboard in this browser', }); @@ -46,7 +46,7 @@ export const copyValueToClipboard = ({ return null; } - const toastTitle = i18n.translate('discover.grid.copyValueToClipboard.toastTitle', { + const toastTitle = i18n.translate('unifiedDataTable.copyValueToClipboard.toastTitle', { defaultMessage: 'Copied to clipboard', }); @@ -105,7 +105,7 @@ export const copyColumnValuesToClipboard = async ({ return null; } - const toastTitle = i18n.translate('discover.grid.copyColumnValuesToClipboard.toastTitle', { + const toastTitle = i18n.translate('unifiedDataTable.copyColumnValuesToClipboard.toastTitle', { defaultMessage: 'Values of "{column}" column copied to clipboard', values: { column: columnDisplayName }, }); @@ -143,7 +143,7 @@ export const copyColumnNameToClipboard = ({ return null; } - const toastTitle = i18n.translate('discover.grid.copyColumnNameToClipboard.toastTitle', { + const toastTitle = i18n.translate('unifiedDataTable.copyColumnNameToClipboard.toastTitle', { defaultMessage: 'Copied to clipboard', }); diff --git a/src/plugins/discover/public/utils/get_field_capabilities.test.ts b/packages/kbn-unified-data-table/src/utils/get_field_capabilities.test.ts similarity index 100% rename from src/plugins/discover/public/utils/get_field_capabilities.test.ts rename to packages/kbn-unified-data-table/src/utils/get_field_capabilities.test.ts diff --git a/src/plugins/discover/public/utils/get_field_capabilities.ts b/packages/kbn-unified-data-table/src/utils/get_field_capabilities.ts similarity index 90% rename from src/plugins/discover/public/utils/get_field_capabilities.ts rename to packages/kbn-unified-data-table/src/utils/get_field_capabilities.ts index cd63c1c189e73..8374801ec311e 100644 --- a/src/plugins/discover/public/utils/get_field_capabilities.ts +++ b/packages/kbn-unified-data-table/src/utils/get_field_capabilities.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/common'; export const getFieldCapabilities = (dataView: DataView, field: DataViewField) => { const isRuntimeField = Boolean(dataView.getFieldByName(field.name)?.runtimeField); diff --git a/src/plugins/discover/public/components/discover_grid/get_render_cell_value.test.tsx b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx similarity index 76% rename from src/plugins/discover/public/components/discover_grid/get_render_cell_value.test.tsx rename to packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx index 229c730ea9dbd..941dccabf2474 100644 --- a/src/plugins/discover/public/components/discover_grid/get_render_cell_value.test.tsx +++ b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx @@ -13,9 +13,38 @@ import { findTestSubject } from '@elastic/eui/lib/test'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { getRenderCellValueFn } from './get_render_cell_value'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { CodeEditorProps, KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { buildDataTableRecord } from '@kbn/discover-utils'; import type { EsHitRecord } from '@kbn/discover-utils/types'; +import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; + +jest.mock('@kbn/code-editor', () => { + const original = jest.requireActual('@kbn/code-editor'); + + const CodeEditorMock = (props: CodeEditorProps) => ( + + ); + + return { + ...original, + CodeEditor: CodeEditorMock, + }; +}); + +window.matchMedia = jest.fn().mockImplementation((query) => { + return { + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), + removeListener: jest.fn(), + }; +}); const mockServices = { settings: { @@ -34,14 +63,6 @@ const mockServices = { }, }; -jest.mock('../../hooks/use_discover_services', () => { - const originalModule = jest.requireActual('../../hooks/use_discover_services'); - return { - ...originalModule, - useDiscoverServices: () => mockServices, - }; -}); - const rowsSource: EsHitRecord[] = [ { _id: '1', @@ -82,18 +103,19 @@ const rowsFieldsWithTopLevelObject: EsHitRecord[] = [ const build = (hit: EsHitRecord) => buildDataTableRecord(hit, dataViewMock); -describe('Discover grid cell rendering', function () { +describe('Unified data table cell rendering', function () { it('renders bytes column correctly', () => { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsSource.map(build), false, () => false, - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - ); expect(component.html()).toMatchInlineSnapshot( - `"100"` + `"100"` ); }); it('renders bytes column correctly using _source when details is true', () => { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsSource.map(build), false, () => false, - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - ); expect(component.html()).toMatchInlineSnapshot( - `"
    100
    "` + `"
    100
    "` ); }); it('renders bytes column correctly using fields when details is true', () => { const closePopoverMockFn = jest.fn(); - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFields.map(build), false, () => false, - 100, - closePopoverMockFn + closePopoverMockFn, + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = mountWithIntl( - ); expect(component.html()).toMatchInlineSnapshot( - `"
    100
    "` + `"
    100
    "` ); findTestSubject(component, 'docTableClosePopover').simulate('click'); expect(closePopoverMockFn).toHaveBeenCalledTimes(1); }); it('renders _source column correctly', () => { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsSource.map(build), false, (fieldName) => ['extension', 'bytes'].includes(fieldName), - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - @@ -191,7 +216,7 @@ describe('Discover grid cell rendering', function () { extension { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsSource.map(build), false, () => false, - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFields.map(build), true, (fieldName) => ['extension', 'bytes'].includes(fieldName), - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - @@ -340,7 +367,7 @@ describe('Discover grid cell rendering', function () { extension { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFields.map(build), true, (fieldName) => ['extension', 'bytes'].includes(fieldName), + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, // this is the number of rendered items - 1, - jest.fn() + 1 ); const component = shallow( - @@ -419,7 +447,7 @@ describe('Discover grid cell rendering', function () { extension { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFields.map(build), true, (fieldName) => false, - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFieldsWithTopLevelObject.map(build), true, (fieldName) => ['object.value', 'extension', 'bytes'].includes(fieldName), - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - @@ -577,7 +607,7 @@ describe('Discover grid cell rendering', function () { object.value { (dataViewMock.getFieldByName as jest.Mock).mockReturnValueOnce(undefined); - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFieldsWithTopLevelObject.map(build), true, (fieldName) => ['extension', 'bytes', 'object.value'].includes(fieldName), - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - @@ -619,7 +650,7 @@ describe('Discover grid cell rendering', function () { object.value { const closePopoverMockFn = jest.fn(); - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFieldsWithTopLevelObject.map(build), true, () => false, - 100, - closePopoverMockFn + closePopoverMockFn, + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - { const closePopoverMockFn = jest.fn(); - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFieldsWithTopLevelObject.map(build), true, () => false, - 100, - closePopoverMockFn + closePopoverMockFn, + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = mountWithIntl( - { (dataViewMock.getFieldByName as jest.Mock).mockReturnValueOnce(undefined); - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFieldsWithTopLevelObject.map(build), true, () => false, - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsSource.map(build), false, () => false, - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - ); expect(component.html()).toMatchInlineSnapshot( - `"-"` + `"-"` ); }); it('renders correctly when invalid column is given', () => { - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsSource.map(build), false, () => false, - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - ); expect(component.html()).toMatchInlineSnapshot( - `"-"` + `"-"` ); }); @@ -824,16 +860,17 @@ describe('Discover grid cell rendering', function () { }, }, ]; - const DiscoverGridCellValue = getRenderCellValueFn( + const DataTableCellValue = getRenderCellValueFn( dataViewMock, rowsFieldsUnmapped.map(build), true, (fieldName) => ['unmapped'].includes(fieldName), - 100, - jest.fn() + jest.fn(), + mockServices.fieldFormats as unknown as FieldFormatsStart, + 100 ); const component = shallow( - void + closePopover: () => void, + fieldFormats: FieldFormatsStart, + maxEntries: number, + externalCustomRenderers?: Record< + string, + (props: EuiDataGridCellValueElementProps) => React.ReactNode + > ) => - ({ rowIndex, columnId, isDetails, setCellProps }: EuiDataGridCellValueElementProps) => { - const { uiSettings, fieldFormats } = useDiscoverServices(); - - const maxEntries = useMemo(() => uiSettings.get(MAX_DOC_FIELDS_DISPLAYED), [uiSettings]); - + ({ + rowIndex, + columnId, + isDetails, + setCellProps, + colIndex, + isExpandable, + isExpanded, + }: EuiDataGridCellValueElementProps) => { + if (!!externalCustomRenderers && !!externalCustomRenderers[columnId]) { + return ( + <> + {externalCustomRenderers[columnId]({ + rowIndex, + columnId, + isDetails, + setCellProps, + isExpandable, + isExpanded, + colIndex, + })} + + ); + } const row = rows ? rows[rowIndex] : undefined; const field = dataView.fields.getByName(columnId); - const ctx = useContext(DiscoverGridContext); + const ctx = useContext(UnifiedDataTableContext); useEffect(() => { if (row?.isAnchor) { @@ -102,7 +125,7 @@ export const getRenderCellValueFn = const pairs = useTopLevelObjectColumns ? getTopLevelObjectPairs(row.raw, columnId, dataView, shouldShowFieldHandler).slice( 0, - maxDocFieldsDisplayed + maxEntries ) : formatHit(row, dataView, shouldShowFieldHandler, maxEntries, fieldFormats); @@ -110,13 +133,13 @@ export const getRenderCellValueFn = {pairs.map(([key, value]) => ( {key} @@ -144,7 +167,7 @@ export const getRenderCellValueFn = function getInnerColumns(fields: Record, columnId: string) { return Object.fromEntries( Object.entries(fields).filter(([key]) => { - return key.indexOf(`${columnId}.`) === 0; + return key.startsWith(`${columnId}.`); }) ); } @@ -178,7 +201,7 @@ function renderPopoverContent({ }) { const closeButton = ( @@ -216,7 +239,7 @@ function renderPopoverContent({ String(v) }; - const formatted = (values as unknown[]) + const formatted = values .map((val: unknown) => formatter.convert(val, 'html', { field: subField, diff --git a/src/plugins/discover/public/utils/popularize_field.test.ts b/packages/kbn-unified-data-table/src/utils/popularize_field.test.ts similarity index 100% rename from src/plugins/discover/public/utils/popularize_field.test.ts rename to packages/kbn-unified-data-table/src/utils/popularize_field.test.ts diff --git a/src/plugins/discover/public/utils/popularize_field.ts b/packages/kbn-unified-data-table/src/utils/popularize_field.ts similarity index 89% rename from src/plugins/discover/public/utils/popularize_field.ts rename to packages/kbn-unified-data-table/src/utils/popularize_field.ts index 9ab711be49266..3feca3fd3d4e7 100644 --- a/src/plugins/discover/public/utils/popularize_field.ts +++ b/packages/kbn-unified-data-table/src/utils/popularize_field.ts @@ -7,8 +7,8 @@ */ import type { Capabilities } from '@kbn/core/public'; -import { DataViewsContract } from '@kbn/data-plugin/public'; -import { DataView } from '@kbn/data-views-plugin/public'; +import type { DataViewsContract } from '@kbn/data-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; async function popularizeField( dataView: DataView, diff --git a/src/plugins/discover/public/utils/row_heights.ts b/packages/kbn-unified-data-table/src/utils/row_heights.ts similarity index 70% rename from src/plugins/discover/public/utils/row_heights.ts rename to packages/kbn-unified-data-table/src/utils/row_heights.ts index f1e096b76b9f9..45f472286d030 100644 --- a/src/plugins/discover/public/utils/row_heights.ts +++ b/packages/kbn-unified-data-table/src/utils/row_heights.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Storage } from '@kbn/kibana-utils-plugin/public'; +import type { Storage } from '@kbn/kibana-utils-plugin/public'; import { isValidRowHeight } from './validate_row_height'; export interface DataGridOptionsRecord { @@ -14,10 +14,13 @@ export interface DataGridOptionsRecord { previousConfigRowHeight: number; } -const ROW_HEIGHT_KEY = 'discover:dataGridRowHeight'; +const getRowHeightKey = (consumer: string) => `${consumer}:dataGridRowHeight`; -export const getStoredRowHeight = (storage: Storage): DataGridOptionsRecord | null => { - const entry = storage.get(ROW_HEIGHT_KEY); +export const getStoredRowHeight = ( + storage: Storage, + consumer: string +): DataGridOptionsRecord | null => { + const entry = storage.get(getRowHeightKey(consumer)); if ( typeof entry === 'object' && entry !== null && @@ -32,9 +35,10 @@ export const getStoredRowHeight = (storage: Storage): DataGridOptionsRecord | nu export const updateStoredRowHeight = ( newRowHeight: number, configRowHeight: number, - storage: Storage + storage: Storage, + consumer: string ) => { - storage.set(ROW_HEIGHT_KEY, { + storage.set(getRowHeightKey(consumer), { previousRowHeight: newRowHeight, previousConfigRowHeight: configRowHeight, }); diff --git a/src/plugins/discover/public/utils/rows_per_page.test.ts b/packages/kbn-unified-data-table/src/utils/rows_per_page.test.ts similarity index 58% rename from src/plugins/discover/public/utils/rows_per_page.test.ts rename to packages/kbn-unified-data-table/src/utils/rows_per_page.test.ts index 25eddf9a44de2..8da8ea099734b 100644 --- a/src/plugins/discover/public/utils/rows_per_page.test.ts +++ b/packages/kbn-unified-data-table/src/utils/rows_per_page.test.ts @@ -6,9 +6,7 @@ * Side Public License, v 1. */ -import { discoverServiceMock } from '../__mocks__/services'; -import { SAMPLE_ROWS_PER_PAGE_SETTING } from '@kbn/discover-utils'; -import { getRowsPerPageOptions, getDefaultRowsPerPage } from './rows_per_page'; +import { getRowsPerPageOptions } from './rows_per_page'; const SORTED_OPTIONS = [10, 25, 50, 100, 250, 500]; @@ -26,17 +24,4 @@ describe('rows per page', () => { expect(getRowsPerPageOptions(350)).toEqual([10, 25, 50, 100, 250, 350, 500]); }); }); - - describe('getDefaultRowsPerPage', () => { - it('should return a value from settings', () => { - expect(getDefaultRowsPerPage(discoverServiceMock.uiSettings)).toEqual(150); - expect(discoverServiceMock.uiSettings.get).toHaveBeenCalledWith(SAMPLE_ROWS_PER_PAGE_SETTING); - }); - - it('should return a default value', () => { - expect(getDefaultRowsPerPage({ ...discoverServiceMock.uiSettings, get: jest.fn() })).toEqual( - 100 - ); - }); - }); }); diff --git a/src/plugins/discover/public/utils/rows_per_page.ts b/packages/kbn-unified-data-table/src/utils/rows_per_page.ts similarity index 62% rename from src/plugins/discover/public/utils/rows_per_page.ts rename to packages/kbn-unified-data-table/src/utils/rows_per_page.ts index bc5f07f6253d3..2eb547df1a36f 100644 --- a/src/plugins/discover/public/utils/rows_per_page.ts +++ b/packages/kbn-unified-data-table/src/utils/rows_per_page.ts @@ -7,9 +7,8 @@ */ import { sortBy, uniq } from 'lodash'; -import { SAMPLE_ROWS_PER_PAGE_SETTING } from '@kbn/discover-utils'; -import { DEFAULT_ROWS_PER_PAGE, ROWS_PER_PAGE_OPTIONS } from '../../common/constants'; -import { DiscoverServices } from '../build_services'; + +import { ROWS_PER_PAGE_OPTIONS } from '../constants'; export const getRowsPerPageOptions = (currentRowsPerPage?: number): number[] => { return sortBy( @@ -20,7 +19,3 @@ export const getRowsPerPageOptions = (currentRowsPerPage?: number): number[] => ) ); }; - -export const getDefaultRowsPerPage = (uiSettings: DiscoverServices['uiSettings']): number => { - return parseInt(uiSettings.get(SAMPLE_ROWS_PER_PAGE_SETTING), 10) || DEFAULT_ROWS_PER_PAGE; -}; diff --git a/src/plugins/discover/public/utils/validate_row_height.ts b/packages/kbn-unified-data-table/src/utils/validate_row_height.ts similarity index 100% rename from src/plugins/discover/public/utils/validate_row_height.ts rename to packages/kbn-unified-data-table/src/utils/validate_row_height.ts diff --git a/packages/kbn-unified-data-table/tsconfig.json b/packages/kbn-unified-data-table/tsconfig.json new file mode 100644 index 0000000000000..bed8d16a279b1 --- /dev/null +++ b/packages/kbn-unified-data-table/tsconfig.json @@ -0,0 +1,37 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types" + }, + "include": ["*.ts", "**/*.tsx", "src/**/*", "__mocks__/**/*.ts"], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/i18n", + "@kbn/data-views-plugin", + "@kbn/unified-doc-viewer", + "@kbn/discover-utils", + "@kbn/kibana-utils-plugin", + "@kbn/expressions-plugin", + "@kbn/test-jest-helpers", + "@kbn/i18n-react", + "@kbn/ui-theme", + "@kbn/field-types", + "@kbn/kibana-utils-plugin", + "@kbn/cell-actions", + "@kbn/utility-types", + "@kbn/data-view-field-editor-plugin", + "@kbn/field-formats-plugin", + "@kbn/react-kibana-context-common", + "@kbn/data-plugin", + "@kbn/core", + "@kbn/ui-actions-plugin", + "@kbn/charts-plugin", + "@kbn/kibana-react-plugin", + "@kbn/monaco", + "@kbn/code-editor", + "@kbn/config", + "@kbn/monaco", + ] +} diff --git a/packages/kbn-unified-doc-viewer/README.md b/packages/kbn-unified-doc-viewer/README.md new file mode 100644 index 0000000000000..825f6eee9f910 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/README.md @@ -0,0 +1,15 @@ +# @kbn/unified-doc-viewer + +This package contains components and services for the unified doc viewer component. + +Discover (Classic view → Expanded document) + +![image](https://github.com/elastic/kibana/assets/1178348/a0a360bf-2697-4427-a32e-c728f06f5a7e) + +Discover (Document explorer → Toggle dialog with details) + +![image](https://github.com/elastic/kibana/assets/1178348/c9c11587-c53f-4bcd-8d48-aaceb64981ea) + +Discover (View single document) + +![image](https://github.com/elastic/kibana/assets/1178348/4a8ea694-d4f5-4c9c-9259-1212f0d50a18) diff --git a/packages/kbn-unified-doc-viewer/index.ts b/packages/kbn-unified-doc-viewer/index.ts new file mode 100644 index 0000000000000..47aae8b209ac3 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/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 { DocViewer, DocViewsRegistry, ElasticRequestState, FieldName } from './src'; diff --git a/packages/kbn-unified-doc-viewer/jest.config.js b/packages/kbn-unified-doc-viewer/jest.config.js new file mode 100644 index 0000000000000..1abe8ad8e52e9 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/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-unified-doc-viewer'], +}; diff --git a/packages/kbn-unified-doc-viewer/kibana.jsonc b/packages/kbn-unified-doc-viewer/kibana.jsonc new file mode 100644 index 0000000000000..272c2ec69ce82 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/unified-doc-viewer", + "owner": "@elastic/kibana-data-discovery" +} diff --git a/packages/kbn-unified-doc-viewer/package.json b/packages/kbn-unified-doc-viewer/package.json new file mode 100644 index 0000000000000..c301255f057bc --- /dev/null +++ b/packages/kbn-unified-doc-viewer/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/unified-doc-viewer", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0", + "sideEffects": false +} \ No newline at end of file diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap similarity index 95% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap rename to packages/kbn-unified-doc-viewer/src/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap index ad0ee0fa4dc95..83dde56a57228 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap +++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Render with 3 different tabs 1`] = ` +exports[` Render with 3 different tabs 1`] = `
    ', () => { + test('Render with 3 different tabs', () => { + const registry = new DocViewsRegistry(); + registry.addDocView({ order: 10, title: 'Render function', render: jest.fn() }); + registry.addDocView({ order: 20, title: 'React component', component: () =>
    test
    }); + // @ts-expect-error This should be invalid and will throw an error when rendering + registry.addDocView({ order: 30, title: 'Invalid doc view' }); + + const renderProps = { hit: {} } as DocViewRenderProps; + + const wrapper = shallow( + + ); + + expect(wrapper).toMatchSnapshot(); + }); + + test('Render with 1 tab displaying error message', () => { + function SomeComponent() { + // this is just a placeholder + return null; + } + + const registry = new DocViewsRegistry(); + registry.addDocView({ + order: 10, + title: 'React component', + component: SomeComponent, + }); + + const renderProps = { + hit: buildDataTableRecord({ _index: 't', _id: '1' }), + } as DocViewRenderProps; + const errorMsg = 'Catch me if you can!'; + + const wrapper = mount( + + ); + const error = new Error(errorMsg); + wrapper.find(SomeComponent).simulateError(error); + const errorMsgComponent = findTestSubject(wrapper, 'docViewerError'); + expect(errorMsgComponent.text()).toMatch(new RegExp(`${errorMsg}`)); + }); +}); diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx similarity index 57% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer.tsx rename to packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx index c2532735641f9..901208f8b3988 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer.tsx +++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx @@ -8,9 +8,12 @@ import React from 'react'; import { EuiTabbedContent } from '@elastic/eui'; -import { getDocViewsRegistry } from '../../../../kibana_services'; import { DocViewerTab } from './doc_viewer_tab'; -import { DocView, DocViewRenderProps } from '../../doc_views_types'; +import type { DocView, DocViewRenderProps } from '../../types'; + +export interface DocViewerProps extends DocViewRenderProps { + docViews: DocView[]; +} /** * Rendering tabs with different views of 1 Elasticsearch hit in Discover. @@ -18,26 +21,23 @@ import { DocView, DocViewRenderProps } from '../../doc_views_types'; * A view can contain a React `component`, or any JS framework by using * a `render` function. */ -export function DocViewer(renderProps: DocViewRenderProps) { - const docViewsRegistry = getDocViewsRegistry(); - const tabs = docViewsRegistry - .getDocViewsSorted(renderProps.hit) - .map(({ title, render, component }: DocView, idx: number) => { - return { - id: `kbn_doc_viewer_tab_${idx}`, - name: title, - content: ( - - ), - ['data-test-subj']: `docViewerTab-${idx}`, - }; - }); +export function DocViewer({ docViews, ...renderProps }: DocViewerProps) { + const tabs = docViews.map(({ title, render, component }: DocView, idx: number) => { + return { + id: `kbn_doc_viewer_tab_${idx}`, + name: title, + content: ( + + ), + ['data-test-subj']: `docViewerTab-${idx}`, + }; + }); if (!tabs.length) { // There there's a minimum of 2 tabs active in Discover. diff --git a/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_error.test.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_error.test.tsx new file mode 100644 index 0000000000000..e21d0d772ecb5 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_error.test.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { DocViewerError } from './doc_viewer_error'; + +test('DocViewerError should wrap error in boundary', () => { + const props = { + error: new Error('my error'), + }; + + expect(() => { + const wrapper = mount(); + const html = wrapper.html(); + expect(html).toContain('euiErrorBoundary'); + expect(html).toContain('my error'); + }).not.toThrowError(); +}); diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_render_error.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_error.tsx similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_render_error.tsx rename to packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_error.tsx diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_render_tab.test.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_render_tab.test.tsx similarity index 93% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_render_tab.test.tsx rename to packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_render_tab.test.tsx index 5c61938a9e830..1aa7372c65fb5 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_render_tab.test.tsx +++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_render_tab.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { mount } from 'enzyme'; import { DocViewRenderTab } from './doc_viewer_render_tab'; -import { DocViewRenderProps } from '../../doc_views_types'; +import type { DocViewRenderProps } from '../../types'; test('Mounting and unmounting DocViewerRenderTab', () => { const unmountFn = jest.fn(); diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_render_tab.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_render_tab.tsx similarity index 92% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_render_tab.tsx rename to packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_render_tab.tsx index 257f40a9850a1..5471bb52104bc 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_render_tab.tsx +++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_render_tab.tsx @@ -7,7 +7,7 @@ */ import React, { useRef, useEffect } from 'react'; -import { DocViewRenderFn, DocViewRenderProps } from '../../doc_views_types'; +import type { DocViewRenderFn, DocViewRenderProps } from '../../types'; interface Props { render: DocViewRenderFn; diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_tab.test.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_tab.test.tsx similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_tab.test.tsx rename to packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_tab.test.tsx diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_tab.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_tab.tsx similarity index 94% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_tab.tsx rename to packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_tab.tsx index 837ee910176b9..ce88120c1d196 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer_tab.tsx +++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer_tab.tsx @@ -9,8 +9,8 @@ import React from 'react'; import { isEqual } from 'lodash'; import { DocViewRenderTab } from './doc_viewer_render_tab'; -import { DocViewerError } from './doc_viewer_render_error'; -import { DocViewRenderFn, DocViewRenderProps } from '../../doc_views_types'; +import { DocViewerError } from './doc_viewer_error'; +import type { DocViewRenderFn, DocViewRenderProps } from '../../types'; interface Props { id: number; diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer/index.ts b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/index.ts similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer/index.ts rename to packages/kbn-unified-doc-viewer/src/components/doc_viewer/index.ts diff --git a/src/plugins/discover/public/components/field_name/__snapshots__/field_name.test.tsx.snap b/packages/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap similarity index 100% rename from src/plugins/discover/public/components/field_name/__snapshots__/field_name.test.tsx.snap rename to packages/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap diff --git a/src/plugins/discover/public/components/field_name/__stories__/field_name.stories.tsx b/packages/kbn-unified-doc-viewer/src/components/field_name/__stories__/field_name.stories.tsx similarity index 100% rename from src/plugins/discover/public/components/field_name/__stories__/field_name.stories.tsx rename to packages/kbn-unified-doc-viewer/src/components/field_name/__stories__/field_name.stories.tsx diff --git a/src/plugins/discover/public/components/field_name/field_name.scss b/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.scss similarity index 100% rename from src/plugins/discover/public/components/field_name/field_name.scss rename to packages/kbn-unified-doc-viewer/src/components/field_name/field_name.scss diff --git a/src/plugins/discover/public/components/field_name/field_name.test.tsx b/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.test.tsx similarity index 100% rename from src/plugins/discover/public/components/field_name/field_name.test.tsx rename to packages/kbn-unified-doc-viewer/src/components/field_name/field_name.test.tsx diff --git a/src/plugins/discover/public/components/field_name/field_name.tsx b/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.tsx similarity index 85% rename from src/plugins/discover/public/components/field_name/field_name.tsx rename to packages/kbn-unified-doc-viewer/src/components/field_name/field_name.tsx index b651cca0b7592..824de1da96dbb 100644 --- a/src/plugins/discover/public/components/field_name/field_name.tsx +++ b/packages/kbn-unified-doc-viewer/src/components/field_name/field_name.tsx @@ -12,8 +12,9 @@ import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiToolTip, EuiHighlight } from '@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { FieldIcon, FieldIconProps } from '@kbn/react-field'; -import { type DataViewField, getFieldSubtypeMulti } from '@kbn/data-views-plugin/public'; -import { getFieldTypeName } from '@kbn/unified-field-list/src/utils/field_types/get_field_type_name'; +import type { DataViewField } from '@kbn/data-views-plugin/public'; +import { getDataViewFieldSubtypeMulti } from '@kbn/es-query'; +import { getFieldTypeName } from '@kbn/discover-utils'; interface Props { fieldName: string; @@ -36,7 +37,7 @@ export function FieldName({ const displayName = fieldMapping && fieldMapping.displayName ? fieldMapping.displayName : fieldName; const tooltip = displayName !== fieldName ? `${fieldName} (${displayName})` : fieldName; - const subTypeMulti = fieldMapping && getFieldSubtypeMulti(fieldMapping.spec); + const subTypeMulti = fieldMapping && getDataViewFieldSubtypeMulti(fieldMapping.spec); const isMultiField = !!subTypeMulti?.multi; return ( @@ -62,7 +63,7 @@ export function FieldName({ position="top" delay="long" content={i18n.translate( - 'discover.fieldChooser.discoverField.multiFieldTooltipContent', + 'unifiedDocViewer.fieldChooser.discoverField.multiFieldTooltipContent', { defaultMessage: 'Multi-fields can have multiple values per field', } @@ -75,7 +76,7 @@ export function FieldName({ data-test-subj={`tableDocViewRow-${fieldName}-multifieldBadge`} > diff --git a/packages/kbn-unified-doc-viewer/src/components/field_name/index.ts b/packages/kbn-unified-doc-viewer/src/components/field_name/index.ts new file mode 100644 index 0000000000000..67a2edbe1b440 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/src/components/field_name/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 * from './field_name'; diff --git a/packages/kbn-unified-doc-viewer/src/components/index.ts b/packages/kbn-unified-doc-viewer/src/components/index.ts new file mode 100644 index 0000000000000..0ab434a88fd44 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/src/components/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 * from './doc_viewer'; +export * from './field_name'; diff --git a/packages/kbn-unified-doc-viewer/src/index.ts b/packages/kbn-unified-doc-viewer/src/index.ts new file mode 100644 index 0000000000000..ae2e0bc299be7 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/src/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 * from './components'; +export * from './services'; diff --git a/src/plugins/discover/public/services/doc_views/doc_views_registry.ts b/packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts similarity index 78% rename from src/plugins/discover/public/services/doc_views/doc_views_registry.ts rename to packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts index 9b6f9d2490d80..620c8bc3058de 100644 --- a/src/plugins/discover/public/services/doc_views/doc_views_registry.ts +++ b/packages/kbn-unified-doc-viewer/src/services/doc_views_registry.ts @@ -7,7 +7,15 @@ */ import type { DataTableRecord } from '@kbn/discover-utils/types'; -import { DocView, DocViewInput, DocViewInputFn } from './doc_views_types'; +import { DocView, DocViewInput, DocViewInputFn } from './types'; + +export enum ElasticRequestState { + Loading, + NotFound, + Found, + Error, + NotFoundDataView, +} export class DocViewsRegistry { private docViews: DocView[] = []; @@ -17,10 +25,10 @@ export class DocViewsRegistry { */ addDocView(docViewRaw: DocViewInput | DocViewInputFn) { const docView = typeof docViewRaw === 'function' ? docViewRaw() : docViewRaw; - if (typeof docView.shouldShow !== 'function') { - docView.shouldShow = () => true; - } - this.docViews.push(docView as DocView); + this.docViews.push({ + ...docView, + shouldShow: docView.shouldShow ?? (() => true), + }); } /** * Returns a sorted array of doc_views for rendering tabs diff --git a/packages/kbn-unified-doc-viewer/src/services/index.ts b/packages/kbn-unified-doc-viewer/src/services/index.ts new file mode 100644 index 0000000000000..c1094d0d7a348 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/src/services/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 { DocViewsRegistry, ElasticRequestState } from './doc_views_registry'; diff --git a/src/plugins/discover/public/services/doc_views/doc_views_types.ts b/packages/kbn-unified-doc-viewer/src/services/types.ts similarity index 96% rename from src/plugins/discover/public/services/doc_views/doc_views_types.ts rename to packages/kbn-unified-doc-viewer/src/services/types.ts index 4fc94580ba29a..0cce5ea3ff813 100644 --- a/src/plugins/discover/public/services/doc_views/doc_views_types.ts +++ b/packages/kbn-unified-doc-viewer/src/services/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import type { AggregateQuery, Query } from '@kbn/es-query'; import type { DataTableRecord, IgnoredReason } from '@kbn/discover-utils/types'; diff --git a/packages/kbn-unified-doc-viewer/src/types.ts b/packages/kbn-unified-doc-viewer/src/types.ts new file mode 100644 index 0000000000000..569665fcc6d87 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/src/types.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { + DocView, + DocViewFilterFn, + DocViewRenderFn, + DocViewRenderProps, + FieldRecordLegacy, +} from './services/types'; diff --git a/packages/kbn-unified-doc-viewer/tsconfig.json b/packages/kbn-unified-doc-viewer/tsconfig.json new file mode 100644 index 0000000000000..856fbe93d6b0f --- /dev/null +++ b/packages/kbn-unified-doc-viewer/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/discover-utils", + "@kbn/data-views-plugin", + "@kbn/es-query", + "@kbn/data-plugin", + "@kbn/i18n-react", + "@kbn/i18n", + "@kbn/react-field", + ] +} diff --git a/packages/kbn-unified-doc-viewer/types.ts b/packages/kbn-unified-doc-viewer/types.ts new file mode 100644 index 0000000000000..d4543a112d9e1 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/types.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 type { ElasticRequestState } from '.'; +export type { DocViewFilterFn, DocViewRenderProps, FieldRecordLegacy } from './src/types'; diff --git a/packages/kbn-unified-field-list/index.ts b/packages/kbn-unified-field-list/index.ts index fed0bc2e736e2..ffee31c4642fc 100755 --- a/packages/kbn-unified-field-list/index.ts +++ b/packages/kbn-unified-field-list/index.ts @@ -48,7 +48,6 @@ export type { AddFieldFilterHandler, FieldListGroups, FieldsGroupDetails, - FieldTypeKnown, FieldListItem, GetCustomFieldType, RenderFieldItemParams, @@ -86,13 +85,7 @@ export { type QuerySubscriberParams, } from './src/hooks/use_query_subscriber'; -export { - getFieldTypeName, - getFieldTypeDescription, - KNOWN_FIELD_TYPES, - getFieldType, - getFieldIconType, -} from './src/utils/field_types'; +export { getFieldTypeDescription, getFieldType, getFieldIconType } from './src/utils/field_types'; export { UnifiedFieldListSidebarContainer, diff --git a/packages/kbn-unified-field-list/src/components/field_icon/field_icon.tsx b/packages/kbn-unified-field-list/src/components/field_icon/field_icon.tsx index 070716911706c..cd6fcb7588fdd 100644 --- a/packages/kbn-unified-field-list/src/components/field_icon/field_icon.tsx +++ b/packages/kbn-unified-field-list/src/components/field_icon/field_icon.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { FieldIcon as KbnFieldIcon, FieldIconProps as KbnFieldIconProps } from '@kbn/react-field'; -import { getFieldTypeName } from '../../utils/field_types'; +import { getFieldTypeName } from '@kbn/discover-utils'; export type FieldIconProps = KbnFieldIconProps; diff --git a/packages/kbn-unified-field-list/src/components/field_list/field_list.tsx b/packages/kbn-unified-field-list/src/components/field_list/field_list.tsx index 9f51fd99e0ed4..8261d5795b61a 100644 --- a/packages/kbn-unified-field-list/src/components/field_list/field_list.tsx +++ b/packages/kbn-unified-field-list/src/components/field_list/field_list.tsx @@ -56,7 +56,14 @@ export const FieldList: React.FC = ({ css={containerStyle} className={className} > - {isProcessing && } + {isProcessing && ( + + )} {!!prepend && {prepend}} {children} {!!append && {append}} diff --git a/packages/kbn-unified-field-list/src/components/field_list_filters/field_type_filter.tsx b/packages/kbn-unified-field-list/src/components/field_list_filters/field_type_filter.tsx index 1afe4bac5f0ba..b1a6387143edd 100644 --- a/packages/kbn-unified-field-list/src/components/field_list_filters/field_type_filter.tsx +++ b/packages/kbn-unified-field-list/src/components/field_list_filters/field_type_filter.tsx @@ -32,15 +32,11 @@ import type { CoreStart } from '@kbn/core-lifecycle-browser'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { type DataViewField } from '@kbn/data-views-plugin/common'; +import type { FieldTypeKnown } from '@kbn/discover-utils/types'; +import { getFieldTypeName, isKnownFieldType, KNOWN_FIELD_TYPE_LIST } from '@kbn/discover-utils'; import { FieldIcon } from '../field_icon'; -import { - getFieldIconType, - getFieldTypeName, - getFieldTypeDescription, - isKnownFieldType, - KNOWN_FIELD_TYPE_LIST, -} from '../../utils/field_types'; -import type { FieldListItem, FieldTypeKnown, GetCustomFieldType } from '../../types'; +import { getFieldIconType, getFieldTypeDescription } from '../../utils/field_types'; +import type { FieldListItem, GetCustomFieldType } from '../../types'; const EQUAL_HEIGHT_OFFSET = 2; // to avoid changes in the header's height after "Clear all" button appears const popoverTitleStyle = css` diff --git a/packages/kbn-unified-field-list/src/hooks/use_field_filters.ts b/packages/kbn-unified-field-list/src/hooks/use_field_filters.ts index c3e08ff335602..0c04ace0911f6 100644 --- a/packages/kbn-unified-field-list/src/hooks/use_field_filters.ts +++ b/packages/kbn-unified-field-list/src/hooks/use_field_filters.ts @@ -10,8 +10,9 @@ import { useMemo, useState } from 'react'; import { htmlIdGenerator } from '@elastic/eui'; import { type DataViewField } from '@kbn/data-views-plugin/common'; import type { CoreStart } from '@kbn/core-lifecycle-browser'; +import type { FieldTypeKnown } from '@kbn/discover-utils/types'; import { type FieldListFiltersProps } from '../components/field_list_filters'; -import { type FieldListItem, type FieldTypeKnown, GetCustomFieldType } from '../types'; +import { type FieldListItem, GetCustomFieldType } from '../types'; import { getFieldIconType } from '../utils/field_types'; import { fieldNameWildcardMatcher } from '../utils/field_name_wildcard_matcher'; diff --git a/packages/kbn-unified-field-list/src/types.ts b/packages/kbn-unified-field-list/src/types.ts index ab9c2af61171a..76997c73176b3 100755 --- a/packages/kbn-unified-field-list/src/types.ts +++ b/packages/kbn-unified-field-list/src/types.ts @@ -8,6 +8,7 @@ import type { DataViewField } from '@kbn/data-views-plugin/common'; import type { EuiButtonIconProps, EuiButtonProps } from '@elastic/eui'; +import type { FieldTypeKnown } from '@kbn/discover-utils/types'; export interface BucketedAggregation { buckets: Array<{ @@ -89,11 +90,6 @@ export type FieldListGroups = { [key in FieldsGroupNames]?: FieldsGroup; }; -export type FieldTypeKnown = Exclude< - DataViewField['timeSeriesMetric'] | DataViewField['type'], - undefined ->; - export type GetCustomFieldType = (field: T) => FieldTypeKnown; export interface RenderFieldItemParams { diff --git a/packages/kbn-unified-field-list/src/utils/field_types/get_field_icon_type.ts b/packages/kbn-unified-field-list/src/utils/field_types/get_field_icon_type.ts index 13ba84121085f..b03ad8cb1389e 100644 --- a/packages/kbn-unified-field-list/src/utils/field_types/get_field_icon_type.ts +++ b/packages/kbn-unified-field-list/src/utils/field_types/get_field_icon_type.ts @@ -7,9 +7,9 @@ */ import { type DataViewField } from '@kbn/data-views-plugin/common'; +import { isKnownFieldType } from '@kbn/discover-utils'; import type { FieldListItem, GetCustomFieldType } from '../../types'; import { getFieldType } from './get_field_type'; -import { isKnownFieldType } from './field_types'; /** * Returns an icon type for a field diff --git a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type.ts b/packages/kbn-unified-field-list/src/utils/field_types/get_field_type.ts index 3ff787188dd06..fc92301b8f8e3 100644 --- a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type.ts +++ b/packages/kbn-unified-field-list/src/utils/field_types/get_field_type.ts @@ -7,7 +7,8 @@ */ import { type DataViewField } from '@kbn/data-views-plugin/common'; -import type { FieldListItem, FieldTypeKnown } from '../../types'; +import type { FieldTypeKnown } from '@kbn/discover-utils/types'; +import type { FieldListItem } from '../../types'; /** * Returns a field type. Time series metric type will override the original field type. diff --git a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_description.test.ts b/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_description.test.ts index 26434008e34ea..8c9ed41e05287 100644 --- a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_description.test.ts +++ b/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_description.test.ts @@ -7,7 +7,7 @@ */ import { getFieldTypeDescription, UNKNOWN_FIELD_TYPE_DESC } from './get_field_type_description'; -import { KNOWN_FIELD_TYPES } from './field_types'; +import { KNOWN_FIELD_TYPES } from '@kbn/discover-utils'; describe('UnifiedFieldList getFieldTypeDescription()', () => { describe('known field types should be recognized', () => { diff --git a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_description.ts b/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_description.ts index cadb07e59eeb4..7f6f9b6e1d765 100644 --- a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_description.ts +++ b/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_description.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; -import { KNOWN_FIELD_TYPES } from './field_types'; +import { KNOWN_FIELD_TYPES } from '@kbn/discover-utils'; /** * A user-friendly description of an unknown field type diff --git a/packages/kbn-unified-field-list/src/utils/field_types/index.ts b/packages/kbn-unified-field-list/src/utils/field_types/index.ts index 732d98e63f8f9..59d09efdd19d6 100644 --- a/packages/kbn-unified-field-list/src/utils/field_types/index.ts +++ b/packages/kbn-unified-field-list/src/utils/field_types/index.ts @@ -6,8 +6,6 @@ * Side Public License, v 1. */ -export { KNOWN_FIELD_TYPES, KNOWN_FIELD_TYPE_LIST, isKnownFieldType } from './field_types'; -export { getFieldTypeName } from './get_field_type_name'; export { getFieldTypeDescription } from './get_field_type_description'; export { getFieldType } from './get_field_type'; export { getFieldIconType } from './get_field_icon_type'; diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 3aeaf04083c66..21ed1425a1cb2 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -151,3 +151,23 @@ export type ArrayElement = A extends ReadonlyArray ? T : never; export type WithRequiredProperty = Omit & { [Property in Key]-?: Type[Property]; }; + +// Recursive partial object type. inspired by EUI RecursivePartial +export type RecursivePartial = { + [P in keyof T]?: T[P] extends NonAny[] + ? T[P] + : T[P] extends readonly NonAny[] + ? T[P] + : T[P] extends Array + ? Array> + : T[P] extends ReadonlyArray + ? ReadonlyArray> + : T[P] extends Set + ? Set> + : T[P] extends Map + ? Map> + : T[P] extends NonAny + ? T[P] + : RecursivePartial; +}; +type NonAny = number | boolean | string | symbol | null; diff --git a/packages/shared-ux/card/no_data/impl/src/no_data_card.tsx b/packages/shared-ux/card/no_data/impl/src/no_data_card.tsx index 22126c6b335e0..2fd29d42224ee 100644 --- a/packages/shared-ux/card/no_data/impl/src/no_data_card.tsx +++ b/packages/shared-ux/card/no_data/impl/src/no_data_card.tsx @@ -35,7 +35,9 @@ export const NoDataCard = ({ href: srcHref, category, description, ...props }: P return ( - + ); }; diff --git a/packages/shared-ux/card/no_data/types/index.d.ts b/packages/shared-ux/card/no_data/types/index.d.ts index 5b2a0b090ffe2..e52843b160639 100644 --- a/packages/shared-ux/card/no_data/types/index.d.ts +++ b/packages/shared-ux/card/no_data/types/index.d.ts @@ -79,4 +79,4 @@ export type NoDataCardComponentProps = Partial< /** * Props for the `NoDataCard` sevice-connected component. */ -export type NoDataCardProps = Omit; +export type NoDataCardProps = NoDataCardComponentProps; diff --git a/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap b/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap index f86ba86999236..b8a983ce582f2 100644 --- a/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap +++ b/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap @@ -351,7 +351,7 @@ exports[` is rendered 1`] = ` = ({ value, onChange, width, + height = '100px', options, overrideEditorWillMount, editorDidMount, @@ -478,7 +479,7 @@ export const CodeEditor: React.FC = ({ onChange={onChange} width={isFullScreen ? '100vw' : width} // previously defaulted to height which defaulted to 100% but this makes it unviewable - height={isFullScreen ? '100vh' : '100px'} + height={isFullScreen ? '100vh' : height} editorWillMount={_editorWillMount} editorDidMount={_editorDidMount} options={{ diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.test.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.test.tsx index 1f657f642fc47..4e16dd6c38bc0 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.test.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.test.tsx @@ -10,7 +10,10 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { I18nProvider } from '@kbn/i18n-react'; + import { KibanaNoDataPage } from '@kbn/shared-ux-page-kibana-no-data'; +import { render, screen } from '@testing-library/react'; import { AnalyticsNoDataPage } from './analytics_no_data_page.component'; import { AnalyticsNoDataPageProvider } from './services'; @@ -28,6 +31,7 @@ describe('AnalyticsNoDataPageComponent', () => { onDataViewCreated={onDataViewCreated} kibanaGuideDocLink={'http://www.test.com'} showPlainSpinner={false} + prependBasePath={(path: string) => path} /> ); @@ -52,6 +56,7 @@ describe('AnalyticsNoDataPageComponent', () => { kibanaGuideDocLink={'http://www.test.com'} allowAdHocDataView={true} showPlainSpinner={false} + prependBasePath={(path: string) => path} /> ); @@ -61,4 +66,86 @@ describe('AnalyticsNoDataPageComponent', () => { expect(component.find(KibanaNoDataPage).length).toBe(1); expect(component.find(KibanaNoDataPage).props().allowAdHocDataView).toBe(true); }); + + describe('no data state', () => { + describe('kibana flavor', () => { + it('renders add integrations card', async () => { + render( + + false }}> + path} + /> + + + ); + + await screen.findByTestId('kbnOverviewAddIntegrations'); + await screen.getAllByText('Add integrations'); + }); + + it('renders disabled add integrations card when fleet is not available', async () => { + render( + + false, canAccessFleet: false }} + > + path} + /> + + + ); + + await screen.findByTestId('kbnOverviewAddIntegrations'); + await screen.getByText('Contact your administrator'); + }); + }); + + describe('serverless_search flavor', () => { + it('renders getting started card', async () => { + render( + + false }}> + path} + /> + + + ); + + await screen.findByTestId('kbnOverviewElasticsearchGettingStarted'); + }); + + it('renders the same getting started card when fleet is not available', async () => { + render( + + false, canAccessFleet: false }} + > + path} + pageFlavor={'serverless_search'} + /> + + + ); + + await screen.findByTestId('kbnOverviewElasticsearchGettingStarted'); + }); + }); + }); }); diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx index d67cb082f5539..4c22a0acb2475 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx @@ -8,6 +8,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { KibanaNoDataPage } from '@kbn/shared-ux-page-kibana-no-data'; +import { KibanaNoDataPageProps } from '@kbn/shared-ux-page-kibana-no-data-types'; +import { AnalyticsNoDataPageFlavor } from '@kbn/shared-ux-page-analytics-no-data-types'; /** * Props for the pure component. @@ -21,26 +23,63 @@ export interface Props { allowAdHocDataView?: boolean; /** if the kibana instance is customly branded */ showPlainSpinner: boolean; + /** The flavor of the empty page to use. */ + pageFlavor?: AnalyticsNoDataPageFlavor; + prependBasePath: (path: string) => string; } -const solution = i18n.translate('sharedUXPackages.noDataConfig.analytics', { - defaultMessage: 'Analytics', -}); - -const pageTitle = i18n.translate('sharedUXPackages.noDataConfig.analyticsPageTitle', { - defaultMessage: 'Welcome to Analytics!', -}); - -const addIntegrationsTitle = i18n.translate('sharedUXPackages.noDataConfig.addIntegrationsTitle', { - defaultMessage: 'Add integrations', -}); - -const addIntegrationsDescription = i18n.translate( - 'sharedUXPackages.noDataConfig.addIntegrationsDescription', - { - defaultMessage: 'Use Elastic Agent to collect data and build out Analytics solutions.', - } -); +const flavors: { + [K in AnalyticsNoDataPageFlavor]: (deps: { + kibanaGuideDocLink: string; + prependBasePath: (path: string) => string; + }) => KibanaNoDataPageProps['noDataConfig']; +} = { + kibana: ({ kibanaGuideDocLink }) => ({ + solution: i18n.translate('sharedUXPackages.noDataConfig.analytics', { + defaultMessage: 'Analytics', + }), + pageTitle: i18n.translate('sharedUXPackages.noDataConfig.analyticsPageTitle', { + defaultMessage: 'Welcome to Analytics!', + }), + logo: 'logoKibana', + action: { + elasticAgent: { + title: i18n.translate('sharedUXPackages.noDataConfig.addIntegrationsTitle', { + defaultMessage: 'Add integrations', + }), + description: i18n.translate('sharedUXPackages.noDataConfig.addIntegrationsDescription', { + defaultMessage: 'Use Elastic Agent to collect data and build out Analytics solutions.', + }), + 'data-test-subj': 'kbnOverviewAddIntegrations', + }, + }, + docsLink: kibanaGuideDocLink, + }), + serverless_search: ({ prependBasePath }) => ({ + solution: i18n.translate('sharedUXPackages.noDataConfig.elasticsearch', { + defaultMessage: 'Elasticsearch', + }), + pageTitle: i18n.translate('sharedUXPackages.noDataConfig.elasticsearchPageTitle', { + defaultMessage: 'Welcome to Elasticsearch!', + }), + logo: 'logoElasticsearch', + action: { + elasticsearch: { + title: i18n.translate('sharedUXPackages.noDataConfig.elasticsearchTitle', { + defaultMessage: 'Get started', + }), + description: i18n.translate('sharedUXPackages.noDataConfig.elasticsearchDescription', { + defaultMessage: + 'Set up your programming language client, ingest some data, and start searching.', + }), + 'data-test-subj': 'kbnOverviewElasticsearchGettingStarted', + href: prependBasePath('/app/elasticsearch/'), + /** force the no data card to be shown **/ + canAccessFleet: true, + }, + }, + }), +}; /** * A pure component of an entire page that can be displayed when Kibana "has no data", specifically for Analytics. @@ -50,20 +89,13 @@ export const AnalyticsNoDataPage = ({ onDataViewCreated, allowAdHocDataView, showPlainSpinner, + prependBasePath, + pageFlavor = 'kibana', }: Props) => { - const noDataConfig = { - solution, - pageTitle, - logo: 'logoKibana', - action: { - elasticAgent: { - title: addIntegrationsTitle, - description: addIntegrationsDescription, - 'data-test-subj': 'kbnOverviewAddIntegrations', - }, - }, - docsLink: kibanaGuideDocLink, - }; + const noDataConfig: KibanaNoDataPageProps['noDataConfig'] = flavors[pageFlavor]({ + kibanaGuideDocLink, + prependBasePath, + }); return ( { expect(component.find(Component).props().kibanaGuideDocLink).toBe(services.kibanaGuideDocLink); expect(component.find(Component).props().onDataViewCreated).toBe(onDataViewCreated); expect(component.find(Component).props().allowAdHocDataView).toBe(true); + expect(component.find(Component).props().prependBasePath).toBe(services.prependBasePath); + expect(component.find(Component).props().pageFlavor).toBe(services.pageFlavor); }); it('passes correct boolean value to showPlainSpinner', () => { diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx index 9b600c374dd02..e9d3ee318d3fd 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx @@ -21,7 +21,7 @@ export const AnalyticsNoDataPage = ({ allowAdHocDataView, }: AnalyticsNoDataPageProps) => { const services = useServices(); - const { kibanaGuideDocLink, customBranding } = services; + const { kibanaGuideDocLink, customBranding, prependBasePath, pageFlavor } = services; const { hasCustomBranding$ } = customBranding; const showPlainSpinner = useObservable(hasCustomBranding$) ?? false; @@ -32,6 +32,8 @@ export const AnalyticsNoDataPage = ({ allowAdHocDataView, kibanaGuideDocLink, showPlainSpinner, + prependBasePath, + pageFlavor, }} /> ); diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/services.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/services.tsx index 991893aeca501..4d514ba032ec9 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/services.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/services.tsx @@ -27,10 +27,10 @@ export const AnalyticsNoDataPageProvider: FC = ({ children, ...services }) => { - const { kibanaGuideDocLink, customBranding } = services; + const { kibanaGuideDocLink, customBranding, prependBasePath, pageFlavor } = services; return ( - + {children} ); @@ -48,6 +48,8 @@ export const AnalyticsNoDataPageKibanaProvider: FC diff --git a/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json b/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json index 6a78f24dff0f7..4b9192a9fd714 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json +++ b/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json @@ -19,6 +19,8 @@ "@kbn/shared-ux-page-analytics-no-data-types", "@kbn/test-jest-helpers", "@kbn/shared-ux-page-analytics-no-data-mocks", + "@kbn/shared-ux-page-kibana-no-data-types", + "@kbn/i18n-react", ], "exclude": [ "target/**/*", diff --git a/packages/shared-ux/page/analytics_no_data/mocks/src/jest.ts b/packages/shared-ux/page/analytics_no_data/mocks/src/jest.ts index 98885d55ba47d..f45d0f72ffed9 100644 --- a/packages/shared-ux/page/analytics_no_data/mocks/src/jest.ts +++ b/packages/shared-ux/page/analytics_no_data/mocks/src/jest.ts @@ -15,6 +15,8 @@ export const getServicesMock = () => { ...getKibanaNoDataPageServicesMock(), kibanaGuideDocLink: 'Kibana guide', customBranding: { hasCustomBranding$: of(false) }, + prependBasePath: (path) => path, + pageFlavor: 'kibana', }; return services; @@ -26,6 +28,8 @@ export const getServicesMockCustomBranding = () => { // this mock will have custom branding set to true customBranding: { hasCustomBranding$: of(true) }, kibanaGuideDocLink: 'Kibana guide', + prependBasePath: (path) => path, + pageFlavor: 'kibana', }; return services; diff --git a/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts b/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts index 86bf25dbde9e9..6bb3f07e34a87 100644 --- a/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts +++ b/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts @@ -51,6 +51,8 @@ export class StorybookMock extends AbstractStorybookMock< customBranding: { hasCustomBranding$: of(false), }, + pageFlavor: 'kibana', + prependBasePath: (path) => path, ...kibanaNoDataMock.getServices(params), }; } diff --git a/packages/shared-ux/page/analytics_no_data/types/index.d.ts b/packages/shared-ux/page/analytics_no_data/types/index.d.ts index 4e54315f071dd..f292e297b6fdc 100644 --- a/packages/shared-ux/page/analytics_no_data/types/index.d.ts +++ b/packages/shared-ux/page/analytics_no_data/types/index.d.ts @@ -17,6 +17,8 @@ import { Observable } from 'rxjs'; export interface Services { kibanaGuideDocLink: string; customBranding: { hasCustomBranding$: Observable }; + prependBasePath: (path: string) => string; + pageFlavor: AnalyticsNoDataPageFlavor; } /** @@ -24,6 +26,8 @@ export interface Services { */ export type AnalyticsNoDataPageServices = Services & KibanaNoDataPageServices; +export type AnalyticsNoDataPageFlavor = 'kibana' | 'serverless_search'; + export interface KibanaDependencies { coreStart: { docLinks: { @@ -36,6 +40,14 @@ export interface KibanaDependencies { customBranding: { hasCustomBranding$: Observable; }; + http: { + basePath: { + prepend: (path: string) => string; + }; + }; + }; + noDataPage?: { + getAnalyticsNoDataPageFlavor: () => AnalyticsNoDataPageFlavor; }; } diff --git a/packages/shared-ux/page/no_data/impl/src/no_data_page.tsx b/packages/shared-ux/page/no_data/impl/src/no_data_page.tsx index 1ba9b18049e87..5aec81d942de6 100644 --- a/packages/shared-ux/page/no_data/impl/src/no_data_page.tsx +++ b/packages/shared-ux/page/no_data/impl/src/no_data_page.tsx @@ -33,13 +33,13 @@ export const NoDataPage = ({ values: { solution }, }); - const link = ( + const link = docsLink ? ( - ); + ) : null; - const message = ( + const message = link ? ( + ) : ( + ); return ( diff --git a/packages/shared-ux/page/no_data/types/index.d.ts b/packages/shared-ux/page/no_data/types/index.d.ts index 3db9e80c950c9..6f29e5ab08d7a 100644 --- a/packages/shared-ux/page/no_data/types/index.d.ts +++ b/packages/shared-ux/page/no_data/types/index.d.ts @@ -31,9 +31,9 @@ export interface NoDataPageProps extends CommonProps, ActionCardProps { */ solution: string; /** - * Required to set the docs link for the whole solution + * Required in "kibana" flavor to set the docs link for the whole solution, otherwise optional */ - docsLink: string; + docsLink?: string; /** * Optionally replace the auto-generated logo */ diff --git a/renovate.json b/renovate.json index a7a16d4fe0307..cab03197e4c42 100644 --- a/renovate.json +++ b/renovate.json @@ -139,6 +139,24 @@ "enabled": true, "prCreation": "immediate" }, + { + "groupName": "ansi-regex", + "matchPackageNames": [ + "ansi-regex" + ], + "reviewers": [ + "team:kibana-core" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "release_note:skip", + "Team:Core", + "backport:skip" + ], + "enabled": true + }, { "groupName": "babel", "matchPackageNames": [ @@ -592,4 +610,4 @@ "enabled": true } ] -} \ No newline at end of file +} diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index 5027d0484fd16..911eecd45a9fb 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -44,6 +44,45 @@ const getBootstrapScript = (isDev) => { } }; +const setServerlessKibanaDevServiceAccountIfPossible = (get, set, opts) => { + const esHosts = [].concat( + get('elasticsearch.hosts', []), + opts.elasticsearch ? opts.elasticsearch.split(',') : [] + ); + + /* + * We only handle the service token if serverless ES is running locally. + * Example would be if the user is running SES in the cloud and KBN serverless + * locally, they would be expected to handle auth on their own and this token + * is likely invalid anyways. + */ + const isESlocalhost = esHosts.length + ? esHosts.some((hostUrl) => { + const parsedUrl = url.parse(hostUrl); + return ( + parsedUrl.hostname === 'localhost' || + parsedUrl.hostname === '127.0.0.1' || + parsedUrl.hostname === 'host.docker.internal' + ); + }) + : true; // default is localhost:9200 + + if (!opts.dev || !opts.serverless || !isESlocalhost) { + return; + } + + const DEV_UTILS_PATH = '@kbn/dev-utils'; + + if (!canRequire(DEV_UTILS_PATH)) { + return; + } + + // need dynamic require to exclude it from production build + // eslint-disable-next-line import/no-dynamic-require + const { kibanaDevServiceAccount } = require(DEV_UTILS_PATH); + set('elasticsearch.serviceAccountToken', kibanaDevServiceAccount.token); +}; + function pathCollector() { const paths = []; return function (path) { @@ -68,6 +107,10 @@ export function applyConfigOverrides(rawConfig, opts, extraCliOptions) { delete extraCliOptions.env; if (opts.dev) { + if (opts.serverless) { + setServerlessKibanaDevServiceAccountIfPossible(get, set, opts); + } + if (!has('elasticsearch.serviceAccountToken') && opts.devCredentials !== false) { if (!has('elasticsearch.username')) { set('elasticsearch.username', 'kibana_system'); @@ -98,7 +141,6 @@ export function applyConfigOverrides(rawConfig, opts, extraCliOptions) { ensureNotDefined('server.ssl.truststore.path'); ensureNotDefined('server.ssl.certificateAuthorities'); ensureNotDefined('elasticsearch.ssl.certificateAuthorities'); - const elasticsearchHosts = ( (customElasticsearchHosts.length > 0 && customElasticsearchHosts) || [ 'https://localhost:9200', diff --git a/src/core/server/integration_tests/config/check_dynamic_config.test.ts b/src/core/server/integration_tests/config/check_dynamic_config.test.ts new file mode 100644 index 0000000000000..7239f051f41e7 --- /dev/null +++ b/src/core/server/integration_tests/config/check_dynamic_config.test.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 { set } from '@kbn/safer-lodash-set'; +import { Root } from '@kbn/core-root-server-internal'; +import { createRootWithCorePlugins } from '@kbn/core-test-helpers-kbn-server'; +import { PLUGIN_SYSTEM_ENABLE_ALL_PLUGINS_CONFIG_PATH } from '@kbn/core-plugins-server-internal/src/constants'; + +describe('checking migration metadata changes on all registered SO types', () => { + let root: Root; + + beforeAll(async () => { + const settings = { + logging: { + loggers: [{ name: 'root', level: 'info', appenders: ['console'] }], + }, + }; + + set(settings, PLUGIN_SYSTEM_ENABLE_ALL_PLUGINS_CONFIG_PATH, true); + + root = createRootWithCorePlugins(settings, { + basePath: false, + cache: false, + dev: true, + disableOptimizer: true, + silent: false, + dist: false, + oss: false, + runExamples: false, + watch: false, + }); + + await root.preboot(); + await root.setup(); + }); + + afterAll(async () => { + if (root) { + await root.shutdown(); + } + }); + + function getListOfDynamicConfigPaths(): string[] { + // eslint-disable-next-line dot-notation + return [...root['server']['configService']['dynamicPaths'].entries()] + .flatMap(([configPath, dynamicConfigKeys]) => { + return dynamicConfigKeys.map( + (dynamicConfigKey: string) => `${configPath}.${dynamicConfigKey}` + ); + }) + .sort(); + } + + /** + * This test is meant to fail when any setting is flagged as capable + * of dynamic configuration {@link PluginConfigDescriptor.dynamicConfig}. + * + * Please, add your settings to the list with a comment of why it's required to be dynamic. + * + * The intent is to trigger a code review from the Core and Security teams to discuss potential issues. + */ + test('detecting all the settings that have opted-in for dynamic in-memory updates', () => { + expect(getListOfDynamicConfigPaths()).toStrictEqual([ + // We need this for enriching our Perf tests with more valuable data regarding the steps of the test + // Also helpful in Cloud & Serverless testing because we can't control the labels in those offerings + 'telemetry.labels', + ]); + }); +}); diff --git a/src/core/server/integration_tests/elasticsearch/capabilities.test.ts b/src/core/server/integration_tests/elasticsearch/capabilities.test.ts new file mode 100644 index 0000000000000..a35c5b1c257f5 --- /dev/null +++ b/src/core/server/integration_tests/elasticsearch/capabilities.test.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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, TestElasticsearchUtils } from '@kbn/core-test-helpers-kbn-server'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { getCapabilitiesFromClient } from '@kbn/core-elasticsearch-server-internal'; + +describe('ES capabilities for traditional ES', () => { + let esServer: TestElasticsearchUtils; + let client: ElasticsearchClient; + + beforeEach(async () => { + const { startES } = createTestServers({ + adjustTimeout: (t: number) => jest.setTimeout(t), + settings: { + es: { + license: 'basic', + }, + }, + }); + + esServer = await startES(); + client = esServer.es.getClient(); + }); + + afterEach(async () => { + if (esServer) { + await esServer.stop(); + } + }); + + it('returns the correct capabilities', async () => { + const capabilities = await getCapabilitiesFromClient(client); + expect(capabilities).toEqual({ + serverless: false, + }); + }); +}); diff --git a/src/core/server/integration_tests/elasticsearch/capabilities_serverless.test.ts b/src/core/server/integration_tests/elasticsearch/capabilities_serverless.test.ts new file mode 100644 index 0000000000000..56754a12daed7 --- /dev/null +++ b/src/core/server/integration_tests/elasticsearch/capabilities_serverless.test.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + TestServerlessESUtils, + createTestServerlessInstances, +} from '@kbn/core-test-helpers-kbn-server'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { getCapabilitiesFromClient } from '@kbn/core-elasticsearch-server-internal'; + +// skipped because test serverless ES nodes are currently using static ports +// causing parallel jest runners to fail for obvious port conflicts reasons. +describe.skip('ES capabilities for serverless ES', () => { + let serverlessES: TestServerlessESUtils; + let client: ElasticsearchClient; + + beforeEach(async () => { + const { startES } = createTestServerlessInstances({ + adjustTimeout: jest.setTimeout, + }); + + serverlessES = await startES(); + client = serverlessES.getClient(); + }); + + afterEach(async () => { + await serverlessES?.stop(); + }); + + it('returns the correct capabilities', async () => { + const capabilities = await getCapabilitiesFromClient(client); + expect(capabilities).toEqual({ + serverless: true, + }); + }); +}); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts index f55c023f6eb74..6bea2a8d7f2e2 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts @@ -106,7 +106,7 @@ describe('checking migration metadata changes on all registered SO types', () => "ingest-agent-policies": "f11cc19275f4c3e4ee7c5cd6423b6706b21b989d", "ingest-download-sources": "279a68147e62e4d8858c09ad1cf03bd5551ce58d", "ingest-outputs": "b4e636b13a5d0f89f0400fb67811d4cca4736eb0", - "ingest-package-policies": "55816507db0134b8efbe0509e311a91ce7e1c6cc", + "ingest-package-policies": "af9e8d523a6f3ae5b8c9adcfba391ff405dfa374", "ingest_manager_settings": "64955ef1b7a9ffa894d4bb9cf863b5602bfa6885", "inventory-view": "b8683c8e352a286b4aca1ab21003115a4800af83", "kql-telemetry": "93c1d16c1a0dfca9c8842062cf5ef8f62ae401ad", @@ -120,7 +120,7 @@ describe('checking migration metadata changes on all registered SO types', () => "ml-module": "2225cbb4bd508ea5f69db4b848be9d8a74b60198", "ml-trained-model": "482195cefd6b04920e539d34d7356d22cb68e4f3", "monitoring-telemetry": "5d91bf75787d9d4dd2fae954d0b3f76d33d2e559", - "observability-onboarding-state": "c18631f47a0da568f12f859c9ab9d4ca73bdff7c", + "observability-onboarding-state": "b16064c516aac64ae699c737d7d10b6e199bfded", "osquery-manager-usage-metric": "983bcbc3b7dda0aad29b20907db233abba709bcc", "osquery-pack": "6ab4358ca4304a12dcfc1777c8135b75cffb4397", "osquery-pack-asset": "b14101d3172c4b60eb5404696881ce5275c84152", diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts index 3800bfc1184ba..dc583d97190a9 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts @@ -13,6 +13,7 @@ import { errors } from '@elastic/elasticsearch'; import type { TaskEither } from 'fp-ts/lib/TaskEither'; import type { SavedObjectsRawDoc } from '@kbn/core-saved-objects-server'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import { createTestServers, type TestElasticsearchUtils } from '@kbn/core-test-helpers-kbn-server'; import { bulkOverwriteTransformedDocuments, @@ -59,16 +60,19 @@ let esServer: TestElasticsearchUtils; describe('migration actions', () => { let client: ElasticsearchClient; + let esCapabilities: ReturnType; beforeAll(async () => { esServer = await startES(); client = esServer.es.getClient().child(MIGRATION_CLIENT_OPTIONS); + esCapabilities = elasticsearchServiceMock.createCapabilities(); // Create test fixture data: await createIndex({ client, indexName: 'existing_index_with_docs', aliases: ['existing_index_with_docs_alias'], + esCapabilities, mappings: { dynamic: true, properties: { @@ -98,11 +102,17 @@ describe('migration actions', () => { refresh: 'wait_for', })(); - await createIndex({ client, indexName: 'existing_index_2', mappings: { properties: {} } })(); + await createIndex({ + client, + indexName: 'existing_index_2', + mappings: { properties: {} }, + esCapabilities, + })(); await createIndex({ client, indexName: 'existing_index_with_write_block', mappings: { properties: {} }, + esCapabilities, })(); await bulkOverwriteTransformedDocuments({ client, @@ -276,6 +286,7 @@ describe('migration actions', () => { client, indexName: 'new_index_without_write_block', mappings: { properties: {} }, + esCapabilities, })(); }); it('resolves right when setting the write block succeeds', async () => { @@ -341,11 +352,13 @@ describe('migration actions', () => { client, indexName: 'existing_index_without_write_block_2', mappings: { properties: {} }, + esCapabilities, })(); await createIndex({ client, indexName: 'existing_index_with_write_block_2', mappings: { properties: {} }, + esCapabilities, })(); await setWriteBlock({ client, index: 'existing_index_with_write_block_2' })(); }); @@ -514,6 +527,7 @@ describe('migration actions', () => { client, source: 'existing_index_with_write_block', target: 'clone_target_1', + esCapabilities, }); expect.assertions(3); await expect(task()).resolves.toMatchInlineSnapshot(` @@ -557,6 +571,7 @@ describe('migration actions', () => { client, source: 'existing_index_with_write_block', target: 'clone_red_then_green_index', + esCapabilities, })(); let indexGreen = false; @@ -609,6 +624,7 @@ describe('migration actions', () => { source: 'existing_index_with_write_block', target: 'clone_red_index', timeout: '1s', + esCapabilities, })(); await expect(cloneIndexPromise).resolves.toMatchInlineSnapshot(` @@ -637,6 +653,7 @@ describe('migration actions', () => { source: 'existing_index_with_write_block', target: 'clone_red_index', timeout: '1s', + esCapabilities, })(); await expect(cloneIndexPromise).resolves.toMatchInlineSnapshot(` @@ -665,6 +682,7 @@ describe('migration actions', () => { source: 'existing_index_with_write_block', target: 'clone_red_index', timeout: '30s', + esCapabilities, })(); await expect(cloneIndexPromise).resolves.toMatchInlineSnapshot(` @@ -679,7 +697,12 @@ describe('migration actions', () => { }); it('resolves left index_not_found_exception if the source index does not exist', async () => { expect.assertions(1); - const task = cloneIndex({ client, source: 'no_such_index', target: 'clone_target_3' }); + const task = cloneIndex({ + client, + source: 'no_such_index', + target: 'clone_target_3', + esCapabilities, + }); await expect(task()).resolves.toMatchInlineSnapshot(` Object { "_tag": "Left", @@ -697,6 +720,7 @@ describe('migration actions', () => { client, source: 'existing_index_with_write_block', target: 'clone_target_4', + esCapabilities, })(); await expect(cloneIndexPromise).resolves.toMatchInlineSnapshot(` Object { @@ -866,7 +890,12 @@ describe('migration actions', () => { expect.assertions(2); // Simulate a reindex that only adds some of the documents from the // source index into the target index - await createIndex({ client, indexName: 'reindex_target_4', mappings: { properties: {} } })(); + await createIndex({ + client, + indexName: 'reindex_target_4', + mappings: { properties: {} }, + esCapabilities, + })(); const response = await client.search({ index: 'existing_index_with_docs', size: 1000 }); const sourceDocs = (response.hits?.hits as SavedObjectsRawDoc[]) .slice(0, 2) @@ -931,6 +960,7 @@ describe('migration actions', () => { /** no title field */ }, }, + esCapabilities, })(); const { @@ -971,6 +1001,7 @@ describe('migration actions', () => { dynamic: false, properties: { title: { type: 'integer' } }, // integer is incompatible with string title }, + esCapabilities, })(); const { @@ -1464,6 +1495,7 @@ describe('migration actions', () => { dynamic: false, properties: {}, }, + esCapabilities, })(); const sourceDocs = [ { _source: { title: 'doc 1' } }, @@ -1769,6 +1801,7 @@ describe('migration actions', () => { indexName: 'create_new_index', mappings: undefined as any, timeout: '1nanos', + esCapabilities, })(); await expect(createIndexPromise).resolves.toEqual({ _tag: 'Right', @@ -1809,6 +1842,7 @@ describe('migration actions', () => { client, indexName: 'red_then_yellow_index', mappings: undefined as any, + esCapabilities, })(); let indexYellow = false; @@ -1861,6 +1895,7 @@ describe('migration actions', () => { client, indexName: 'yellow_then_green_index', mappings: undefined as any, + esCapabilities, })(); let indexGreen = false; @@ -1893,6 +1928,7 @@ describe('migration actions', () => { client, indexName: 'create_index_1', mappings: undefined as any, + esCapabilities, })(); await expect(createIndexPromise).resolves.toMatchInlineSnapshot(` Object { @@ -1907,7 +1943,12 @@ describe('migration actions', () => { // Creating an index with the same name as an existing alias to induce // failure await expect( - createIndex({ client, indexName: 'existing_index_2_alias', mappings: undefined as any })() + createIndex({ + client, + indexName: 'existing_index_2_alias', + mappings: undefined as any, + esCapabilities, + })() ).rejects.toThrow('invalid_index_name_exception'); }); }); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/es_errors.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/es_errors.test.ts index c172aa40312aa..0668b820381c9 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/es_errors.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/es_errors.test.ts @@ -8,6 +8,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { InternalCoreStart } from '@kbn/core-lifecycle-server-internal'; import { Root } from '@kbn/core-root-server-internal'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import type { ElasticsearchClient } from '../../../../..'; import { createRootWithCorePlugins, @@ -48,6 +49,7 @@ describe('Elasticsearch Errors', () => { client, indexName: 'existing_index_with_write_block', mappings: { properties: {} }, + esCapabilities: elasticsearchServiceMock.createCapabilities(), })(); await setWriteBlock({ client, index: 'existing_index_with_write_block' })(); }); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/incompatible_cluster_routing_allocation.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/incompatible_cluster_routing_allocation.test.ts index b723ca1b62608..d663dc15e9a1c 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/incompatible_cluster_routing_allocation.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/incompatible_cluster_routing_allocation.test.ts @@ -125,7 +125,9 @@ describe('incompatible_cluster_routing_allocation', () => { await root.preboot(); await root.setup(); - root.start(); + root.start().catch(() => { + // Silent catch because the test might be done and call shutdown before starting is completed, causing unwanted thrown errors. + }); // Wait for the INIT -> INIT action retry await retryAsync( diff --git a/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts index 26d1b2372a920..6249137d8e7be 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts @@ -16,7 +16,7 @@ import { ConfigService, Env } from '@kbn/config'; import { getEnvOptions } from '@kbn/config-mocks'; import { REPO_ROOT } from '@kbn/repo-info'; import { KibanaMigrator } from '@kbn/core-saved-objects-migration-server-internal'; - +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import { SavedObjectConfig, type SavedObjectsConfigType, @@ -311,6 +311,7 @@ const getMigrator = async ({ docLinks, waitForMigrationCompletion: false, // ensure we have an active role in the migration nodeRoles, + esCapabilities: elasticsearchServiceMock.createCapabilities(), }); }; diff --git a/src/core/server/integration_tests/saved_objects/routes/update.test.ts b/src/core/server/integration_tests/saved_objects/routes/update.test.ts index c261584217a37..e121fa7a43e0d 100644 --- a/src/core/server/integration_tests/saved_objects/routes/update.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/update.test.ts @@ -24,8 +24,8 @@ import { setupConfig } from './routes_test_utils'; type SetupServerReturn = Awaited>; const testTypes = [ - { name: 'index-pattern', hide: false }, - { name: 'hidden-type', hide: true }, + { name: 'index-pattern', hide: false }, // multi-namespace type + { name: 'hidden-type', hide: true }, // hidden { name: 'hidden-from-http', hide: false, hideFromHttpApis: true }, ]; @@ -117,7 +117,7 @@ describe('PUT /api/saved_objects/{type}/{id?}', () => { 'index-pattern', 'logstash-*', { title: 'Testing' }, - { version: 'foo' } + { version: 'foo', migrationVersionCompatibility: 'raw' } ); }); diff --git a/src/core/server/integration_tests/saved_objects/serverless/migrations/smoke.test.ts b/src/core/server/integration_tests/saved_objects/serverless/migrations/smoke.test.ts index 940ea4a160cb6..1d884706fc8ba 100644 --- a/src/core/server/integration_tests/saved_objects/serverless/migrations/smoke.test.ts +++ b/src/core/server/integration_tests/saved_objects/serverless/migrations/smoke.test.ts @@ -13,10 +13,7 @@ import { createTestServerlessInstances, } from '@kbn/core-test-helpers-kbn-server'; -/** - * Until we merge https://github.com/elastic/kibana/pull/162673 this test should remain skipped. - */ -describe.skip('smoke', () => { +describe('smoke', () => { let serverlessES: TestServerlessESUtils; let serverlessKibana: TestServerlessKibanaUtils; let root: TestServerlessKibanaUtils['root']; diff --git a/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy.test.ts b/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy.test.ts index db24bf5a10765..035da58c60fa1 100644 --- a/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy.test.ts +++ b/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy.test.ts @@ -30,6 +30,7 @@ import { declarePostPitRoute, declarePostUpdateByQueryRoute, declarePassthroughRoute, + declareIndexRoute, setProxyInterrupt, allCombinationsPermutations, } from './repository_with_proxy_utils'; @@ -113,6 +114,7 @@ describe('404s from proxies', () => { declarePostSearchRoute(hapiServer, esHostname, esPort, kbnIndexPath); declarePostPitRoute(hapiServer, esHostname, esPort, kbnIndexPath); declarePostUpdateByQueryRoute(hapiServer, esHostname, esPort, kbnIndexPath); + declareIndexRoute(hapiServer, esHostname, esPort, kbnIndexPath); }); // register index-agnostic routes @@ -396,7 +398,9 @@ describe('404s from proxies', () => { expect(genericNotFoundEsUnavailableError(myError, 'my_type', 'myTypeId1')); }); - it('returns an EsUnavailable error on `update` requests that are interrupted', async () => { + it('returns an EsUnavailable error on `update` requests that are interrupted during index', async () => { + setProxyInterrupt('update'); + let updateError; try { await repository.update('my_type', 'myTypeToUpdate', { @@ -406,9 +410,26 @@ describe('404s from proxies', () => { } catch (err) { updateError = err; } + expect(genericNotFoundEsUnavailableError(updateError)); }); + it('returns an EsUnavailable error on `update` requests that are interrupted during preflight', async () => { + setProxyInterrupt('updatePreflight'); + + let updateError; + try { + await repository.update('my_type', 'myTypeToUpdate', { + title: 'updated title', + }); + expect(false).toBe(true); // Should not get here (we expect the call to throw) + } catch (err) { + updateError = err; + } + + expect(genericNotFoundEsUnavailableError(updateError, 'my_type', 'myTypeToUpdate')); + }); + it('returns an EsUnavailable error on `bulkCreate` requests with a 404 proxy response and wrong product header', async () => { setProxyInterrupt('bulkCreate'); let bulkCreateError: any; diff --git a/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy_utils.ts b/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy_utils.ts index 35b6b37b9c413..6f40d19f609d9 100644 --- a/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy_utils.ts +++ b/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy_utils.ts @@ -27,6 +27,8 @@ export const setProxyInterrupt = ( | 'openPit' | 'deleteByNamespace' | 'internalBulkResolve' + | 'update' + | 'updatePreflight' | null ) => (proxyInterrupt = testArg); @@ -63,7 +65,11 @@ export const declareGetRoute = ( path: `/${kbnIndex}/_doc/{type*}`, options: { handler: (req, h) => { - if (req.params.type === 'my_type:myTypeId1' || req.params.type === 'my_type:myType_123') { + if ( + req.params.type === 'my_type:myTypeId1' || + req.params.type === 'my_type:myType_123' || + proxyInterrupt === 'updatePreflight' + ) { return proxyResponseHandler(h, hostname, port); } else { return relayHandler(h, hostname, port); @@ -257,6 +263,31 @@ export const declarePostUpdateByQueryRoute = ( }, }); +// PUT _doc +export const declareIndexRoute = ( + hapiServer: Hapi.Server, + hostname: string, + port: string, + kbnIndex: string +) => + hapiServer.route({ + method: ['PUT', 'POST'], + path: `/${kbnIndex}/_doc/{_id?}`, + options: { + payload: { + output: 'data', + parse: false, + }, + handler: (req, h) => { + if (proxyInterrupt === 'update') { + return proxyResponseHandler(h, hostname, port); + } else { + return relayHandler(h, hostname, port); + } + }, + }, + }); + // catch-all passthrough route export const declarePassthroughRoute = (hapiServer: Hapi.Server, hostname: string, port: string) => hapiServer.route({ diff --git a/src/core/server/integration_tests/saved_objects/service/lib/update.test.ts b/src/core/server/integration_tests/saved_objects/service/lib/update.test.ts new file mode 100644 index 0000000000000..e2b7d91355d81 --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/service/lib/update.test.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Path from 'path'; +import fs from 'fs/promises'; +import { pick } from 'lodash'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { SavedObjectsType, SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server'; +import { type TestElasticsearchUtils } from '@kbn/core-test-helpers-kbn-server'; +import '../../migrations/jest_matchers'; +import { + getKibanaMigratorTestKit, + startElasticsearch, +} from '../../migrations/kibana_migrator_test_kit'; +import { delay } from '../../migrations/test_utils'; +import { getBaseMigratorParams } from '../../migrations/fixtures/zdt_base.fixtures'; + +export const logFilePath = Path.join(__dirname, 'update.test.log'); + +describe('SOR - update API', () => { + let esServer: TestElasticsearchUtils['es']; + + beforeAll(async () => { + await fs.unlink(logFilePath).catch(() => {}); + esServer = await startElasticsearch(); + }); + + const getType = (version: 'v1' | 'v2'): SavedObjectsType => { + const versionMap: SavedObjectsModelVersionMap = { + 1: { + changes: [], + schemas: { + forwardCompatibility: (attributes) => { + return pick(attributes, 'count'); + }, + }, + }, + }; + + if (version === 'v2') { + versionMap[2] = { + changes: [ + { + type: 'data_backfill', + backfillFn: (document) => { + return { attributes: { even: document.attributes.count % 2 === 0 } }; + }, + }, + ], + }; + } + + return { + name: 'my-test-type', + hidden: false, + namespaceType: 'agnostic', + mappings: { + dynamic: false, + properties: { + count: { type: 'integer' }, + ...(version === 'v2' ? { even: { type: 'boolean' } } : {}), + }, + }, + management: { + importableAndExportable: true, + }, + switchToModelVersionAt: '8.10.0', + modelVersions: versionMap, + }; + }; + + afterAll(async () => { + await esServer?.stop(); + await delay(10); + }); + + const setup = async () => { + const { runMigrations: runMigrationV1, savedObjectsRepository: repositoryV1 } = + await getKibanaMigratorTestKit({ + ...getBaseMigratorParams(), + types: [getType('v1')], + }); + await runMigrationV1(); + + const { + runMigrations: runMigrationV2, + savedObjectsRepository: repositoryV2, + client: esClient, + } = await getKibanaMigratorTestKit({ + ...getBaseMigratorParams(), + types: [getType('v2')], + }); + await runMigrationV2(); + + return { repositoryV1, repositoryV2, esClient }; + }; + + it('supports updates between older and newer versions', async () => { + const { repositoryV1, repositoryV2, esClient } = await setup(); + + await repositoryV1.create('my-test-type', { count: 12 }, { id: 'my-id' }); + + let document = await repositoryV2.get('my-test-type', 'my-id'); + + expect(document.attributes).toEqual({ + count: 12, + even: true, + }); + + await repositoryV2.update('my-test-type', 'my-id', { + count: 11, + even: false, + }); + + document = await repositoryV1.get('my-test-type', 'my-id'); + + expect(document.attributes).toEqual({ + count: 11, + }); + + await repositoryV1.update('my-test-type', 'my-id', { + count: 14, + }); + + document = await repositoryV2.get('my-test-type', 'my-id'); + + expect(document.attributes).toEqual({ + count: 14, + even: true, + }); + + const rawDoc = await fetchDoc(esClient, 'my-test-type', 'my-id'); + expect(rawDoc._source).toEqual( + expect.objectContaining({ + typeMigrationVersion: '10.1.0', + 'my-test-type': { + count: 14, + }, + }) + ); + }); + + const fetchDoc = async (client: ElasticsearchClient, type: string, id: string) => { + return await client.get({ + index: '.kibana', + id: `${type}:${id}`, + }); + }; +}); diff --git a/src/core/tsconfig.json b/src/core/tsconfig.json index 20b7911e4f782..8232e102ddab2 100644 --- a/src/core/tsconfig.json +++ b/src/core/tsconfig.json @@ -151,6 +151,7 @@ "@kbn/core-elasticsearch-client-server-internal", "@kbn/tooling-log", "@kbn/stdio-dev-helpers", + "@kbn/safer-lodash-set", ], "exclude": [ "target/**/*", diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile b/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile index a44fae27c4265..8bf470f489cb7 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile @@ -127,6 +127,9 @@ COPY --chown=1000:0 config/serverless.es.yml /usr/share/kibana/config/serverless COPY --chown=1000:0 config/serverless.oblt.yml /usr/share/kibana/config/serverless.oblt.yml COPY --chown=1000:0 config/serverless.security.yml /usr/share/kibana/config/serverless.security.yml {{/serverless}} +{{^opensslLegacyProvider}} +RUN sed 's/\(--openssl-legacy-provider\)/#\1/' -i config/node.options +{{/opensslLegacyProvider}} # Add the launcher/wrapper script. It knows how to interpret environment # variables and translate them to Kibana CLI options. diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts b/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts index ca597e5c38941..456a09ccc3db3 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts @@ -19,6 +19,7 @@ function generator(options: TemplateContext) { packageManager: options.baseImage.includes('ubi') ? 'microdnf' : 'apt-get', ubi: options.baseImage.includes('ubi'), ubuntu: options.baseImage === 'ubuntu', + opensslLegacyProvider: !(options.cloud || options.serverless), ...options, }); } diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index b02009cd155d2..fea9d8629f382 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -27,7 +27,7 @@ export const storybookAliases = { dashboard: 'src/plugins/dashboard/.storybook', data: 'src/plugins/data/.storybook', discover: 'src/plugins/discover/.storybook', - discover_log_explorer: 'x-pack/plugins/discover_log_explorer/.storybook', + log_explorer: 'x-pack/plugins/log_explorer/.storybook', embeddable: 'src/plugins/embeddable/.storybook', es_ui_shared: 'src/plugins/es_ui_shared/.storybook', expression_error: 'src/plugins/expression_error/.storybook', diff --git a/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.tsx b/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.tsx index 97e5979766089..894ea706cccc0 100644 --- a/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.tsx +++ b/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.tsx @@ -762,24 +762,20 @@ export const HeatmapComponent: FC = memo( xAxisTitle={args.gridConfig.isXAxisTitleVisible ? xAxisTitle : undefined} yAxisTitle={args.gridConfig.isYAxisTitleVisible ? yAxisTitle : undefined} xAxisLabelFormatter={(v) => - args.gridConfig.isXAxisLabelVisible - ? `${ - xAccessor && formattedTable.formattedColumns[xAccessor] - ? v - : xValuesFormatter.convert(v) - }` - : '' + `${ + xAccessor && formattedTable.formattedColumns[xAccessor] + ? v + : xValuesFormatter.convert(v) + }` } yAxisLabelFormatter={ yAxisColumn ? (v) => - args.gridConfig.isYAxisLabelVisible - ? `${ - yAccessor && formattedTable.formattedColumns[yAccessor] - ? v - : yValuesFormatter.convert(v) ?? '' - }` - : '' + `${ + yAccessor && formattedTable.formattedColumns[yAccessor] + ? v + : yValuesFormatter.convert(v) ?? '' + }` : undefined } /> diff --git a/src/plugins/console/public/lib/autocomplete/autocomplete.ts b/src/plugins/console/public/lib/autocomplete/autocomplete.ts index 970847ac6bedc..04634e635ac12 100644 --- a/src/plugins/console/public/lib/autocomplete/autocomplete.ts +++ b/src/plugins/console/public/lib/autocomplete/autocomplete.ts @@ -1077,11 +1077,7 @@ export default function ({ tracer('has started evaluating current token', currentToken); if (!currentToken) { - if (pos.lineNumber === 1) { - lastEvaluatedToken = null; - tracer('not starting autocomplete due to invalid current token at line 1'); - return; - } + lastEvaluatedToken = null; currentToken = { position: { column: 0, lineNumber: 0 }, value: '', type: '' }; // empty row } diff --git a/src/plugins/dashboard/kibana.jsonc b/src/plugins/dashboard/kibana.jsonc index c22d68173deb6..0f8601cb96c5d 100644 --- a/src/plugins/dashboard/kibana.jsonc +++ b/src/plugins/dashboard/kibana.jsonc @@ -34,7 +34,8 @@ "screenshotMode", "usageCollection", "taskManager", - "serverless" + "serverless", + "noDataPage" ], "requiredBundles": ["kibanaReact", "kibanaUtils", "presentationUtil"] } diff --git a/src/plugins/dashboard/public/dashboard_app/no_data/dashboard_app_no_data.tsx b/src/plugins/dashboard/public/dashboard_app/no_data/dashboard_app_no_data.tsx index fb04a3187c72c..8580ae2f168d3 100644 --- a/src/plugins/dashboard/public/dashboard_app/no_data/dashboard_app_no_data.tsx +++ b/src/plugins/dashboard/public/dashboard_app/no_data/dashboard_app_no_data.tsx @@ -26,6 +26,7 @@ export const DashboardAppNoDataPage = ({ http: { basePath }, documentationLinks: { indexPatternsDocLink, kibanaGuideDocLink }, customBranding, + noDataPage, } = pluginServices.getServices(); const analyticsServices = { @@ -44,6 +45,7 @@ export const DashboardAppNoDataPage = ({ }, dataViews, dataViewEditor, + noDataPage, }; return ( diff --git a/src/plugins/dashboard/public/dashboard_listing/dashboard_listing_table.tsx b/src/plugins/dashboard/public/dashboard_listing/dashboard_listing_table.tsx index 196fd04cddf6c..2386b414c3209 100644 --- a/src/plugins/dashboard/public/dashboard_listing/dashboard_listing_table.tsx +++ b/src/plugins/dashboard/public/dashboard_listing/dashboard_listing_table.tsx @@ -34,6 +34,7 @@ export const DashboardListingTable = ({ getDashboardUrl, useSessionStorageIntegration, urlStateEnabled, + showCreateDashboardButton = true, }: DashboardListingProps) => { const { application, @@ -61,6 +62,7 @@ export const DashboardListingTable = ({ urlStateEnabled, useSessionStorageIntegration, initialFilter, + showCreateDashboardButton, }); const savedObjectsTaggingFakePlugin = useMemo( diff --git a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx index 7716981e34942..602ac6a1f4a3c 100644 --- a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx +++ b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.test.tsx @@ -105,6 +105,22 @@ describe('useDashboardListingTable', () => { expect(result.current.unsavedDashboardIds).toEqual([]); }); + test('should not render the create dashboard button when showCreateDashboardButton is false', () => { + const initialFilter = 'myFilter'; + const { result } = renderHook(() => + useDashboardListingTable({ + getDashboardUrl, + goToDashboard, + initialFilter, + urlStateEnabled: false, + showCreateDashboardButton: false, + }) + ); + + const tableListViewTableProps = result.current.tableListViewTableProps; + expect(tableListViewTableProps.createItem).toBeUndefined(); + }); + test('should return the correct tableListViewTableProps', () => { const initialFilter = 'myFilter'; const { result } = renderHook(() => diff --git a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx index aefa45500b450..8f2fb7ac76cc9 100644 --- a/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx +++ b/src/plugins/dashboard/public/dashboard_listing/hooks/use_dashboard_listing_table.tsx @@ -70,6 +70,7 @@ export const useDashboardListingTable = ({ initialFilter, urlStateEnabled, useSessionStorageIntegration, + showCreateDashboardButton = true, }: { dashboardListingId?: string; disableCreateDashboardButton?: boolean; @@ -79,6 +80,7 @@ export const useDashboardListingTable = ({ initialFilter?: string; urlStateEnabled?: boolean; useSessionStorageIntegration?: boolean; + showCreateDashboardButton?: boolean; }): UseDashboardListingTableReturnType => { const { dashboardSessionStorage, @@ -274,7 +276,7 @@ export const useDashboardListingTable = ({ onSave: updateItemMeta, customValidators: contentEditorValidators, }, - createItem: !showWriteControls ? undefined : createItem, + createItem: !showWriteControls || !showCreateDashboardButton ? undefined : createItem, deleteItems: !showWriteControls ? undefined : deleteItems, editItem: !showWriteControls ? undefined : editItem, emptyPrompt, @@ -308,6 +310,7 @@ export const useDashboardListingTable = ({ initialPageSize, listingLimit, onFetchSuccess, + showCreateDashboardButton, showWriteControls, title, updateItemMeta, diff --git a/src/plugins/dashboard/public/dashboard_listing/types.ts b/src/plugins/dashboard/public/dashboard_listing/types.ts index c92344d4e778a..18767c1c75c32 100644 --- a/src/plugins/dashboard/public/dashboard_listing/types.ts +++ b/src/plugins/dashboard/public/dashboard_listing/types.ts @@ -17,6 +17,7 @@ export type DashboardListingProps = PropsWithChildren<{ goToDashboard: (dashboardId?: string, viewMode?: ViewMode) => void; getDashboardUrl: (dashboardId: string, usesTimeRestore: boolean) => string; urlStateEnabled?: boolean; + showCreateDashboardButton?: boolean; }>; // because the type of `application.capabilities.advancedSettings` is so generic, the provider diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index a28dbe9c45ae7..d2802a8ef3b6d 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -52,6 +52,7 @@ import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plu import type { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public'; import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import { CustomBrandingStart } from '@kbn/core-custom-branding-browser'; import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; @@ -108,6 +109,7 @@ export interface DashboardStartDependencies { visualizations: VisualizationsStart; customBranding: CustomBrandingStart; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } export interface DashboardSetup { diff --git a/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.stub.ts b/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.stub.ts new file mode 100644 index 0000000000000..c1af1452176a8 --- /dev/null +++ b/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.stub.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 and the Server Side Public License, v 1; you may 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 { PluginServiceFactory } from '@kbn/presentation-util-plugin/public'; +import { NoDataPageService } from './types'; + +export type NoDataPageServiceFactory = PluginServiceFactory; + +export const noDataPageServiceFactory: NoDataPageServiceFactory = () => { + return { getAnalyticsNoDataPageFlavor: () => 'kibana' }; +}; diff --git a/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.ts b/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.ts new file mode 100644 index 0000000000000..f1dded3f12ff3 --- /dev/null +++ b/src/plugins/dashboard/public/services/no_data_page/no_data_page_service.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { KibanaPluginServiceFactory } from '@kbn/presentation-util-plugin/public'; +import { DashboardStartDependencies } from '../../plugin'; +import { NoDataPageService } from './types'; + +export type NoDataPageServiceFactory = KibanaPluginServiceFactory< + NoDataPageService, + DashboardStartDependencies +>; + +export const noDataPageServiceFactory: NoDataPageServiceFactory = ({ startPlugins }) => { + const { noDataPage } = startPlugins; + + return { + getAnalyticsNoDataPageFlavor: noDataPage?.getAnalyticsNoDataPageFlavor ?? (() => 'kibana'), + }; +}; diff --git a/src/plugins/discover/public/components/discover_grid/types.ts b/src/plugins/dashboard/public/services/no_data_page/types.ts similarity index 60% rename from src/plugins/discover/public/components/discover_grid/types.ts rename to src/plugins/dashboard/public/services/no_data_page/types.ts index 71d82e35126ac..7e87f1586db33 100644 --- a/src/plugins/discover/public/components/discover_grid/types.ts +++ b/src/plugins/dashboard/public/services/no_data_page/types.ts @@ -6,13 +6,8 @@ * Side Public License, v 1. */ -/** - * User configurable state of data grid, persisted in saved search - */ -export interface DiscoverGridSettings { - columns?: Record; -} +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; -export interface DiscoverGridSettingsColumn { - width?: number; +export interface NoDataPageService { + getAnalyticsNoDataPageFlavor: NoDataPagePluginStart['getAnalyticsNoDataPageFlavor']; } diff --git a/src/plugins/dashboard/public/services/plugin_services.stub.ts b/src/plugins/dashboard/public/services/plugin_services.stub.ts index 0ae4159ed2128..8ba55d486d75b 100644 --- a/src/plugins/dashboard/public/services/plugin_services.stub.ts +++ b/src/plugins/dashboard/public/services/plugin_services.stub.ts @@ -42,6 +42,7 @@ import { customBrandingServiceFactory } from './custom_branding/custom_branding. import { savedObjectsManagementServiceFactory } from './saved_objects_management/saved_objects_management_service.stub'; import { contentManagementServiceFactory } from './content_management/content_management_service.stub'; import { serverlessServiceFactory } from './serverless/serverless_service.stub'; +import { noDataPageServiceFactory } from './no_data_page/no_data_page_service.stub'; export const providers: PluginServiceProviders = { dashboardContentManagement: new PluginServiceProvider(dashboardContentManagementServiceFactory), @@ -72,6 +73,7 @@ export const providers: PluginServiceProviders = { savedObjectsManagement: new PluginServiceProvider(savedObjectsManagementServiceFactory), contentManagement: new PluginServiceProvider(contentManagementServiceFactory), serverless: new PluginServiceProvider(serverlessServiceFactory), + noDataPage: new PluginServiceProvider(noDataPageServiceFactory), }; export const registry = new PluginServiceRegistry(providers); diff --git a/src/plugins/dashboard/public/services/plugin_services.ts b/src/plugins/dashboard/public/services/plugin_services.ts index d84b55d0ff4a1..f16b4c8f34b0e 100644 --- a/src/plugins/dashboard/public/services/plugin_services.ts +++ b/src/plugins/dashboard/public/services/plugin_services.ts @@ -43,6 +43,7 @@ import { savedObjectsManagementServiceFactory } from './saved_objects_management import { dashboardContentManagementServiceFactory } from './dashboard_content_management/dashboard_content_management_service'; import { contentManagementServiceFactory } from './content_management/content_management_service'; import { serverlessServiceFactory } from './serverless/serverless_service'; +import { noDataPageServiceFactory } from './no_data_page/no_data_page_service'; const providers: PluginServiceProviders = { dashboardContentManagement: new PluginServiceProvider(dashboardContentManagementServiceFactory, [ @@ -86,6 +87,7 @@ const providers: PluginServiceProviders(); diff --git a/src/plugins/dashboard/public/services/types.ts b/src/plugins/dashboard/public/services/types.ts index 13adaf6098070..5ad3aab951121 100644 --- a/src/plugins/dashboard/public/services/types.ts +++ b/src/plugins/dashboard/public/services/types.ts @@ -38,6 +38,7 @@ import { DashboardUrlForwardingService } from './url_forwarding/types'; import { DashboardUsageCollectionService } from './usage_collection/types'; import { DashboardVisualizationsService } from './visualizations/types'; import { DashboardServerlessService } from './serverless/types'; +import { NoDataPageService } from './no_data_page/types'; export type DashboardPluginServiceParams = KibanaPluginServiceParams & { initContext: PluginInitializerContext; // need a custom type so that initContext is a required parameter for initializerContext @@ -72,4 +73,5 @@ export interface DashboardServices { savedObjectsManagement: SavedObjectsManagementPluginStart; contentManagement: ContentManagementPublicStart; serverless: DashboardServerlessService; // TODO: make this optional in follow up + noDataPage: NoDataPageService; } diff --git a/src/plugins/dashboard/tsconfig.json b/src/plugins/dashboard/tsconfig.json index 9d5dafa47c88a..31cc2b1aab236 100644 --- a/src/plugins/dashboard/tsconfig.json +++ b/src/plugins/dashboard/tsconfig.json @@ -64,7 +64,8 @@ "@kbn/content-management-table-list-view-table", "@kbn/shared-ux-prompt-not-found", "@kbn/content-management-content-editor", - "@kbn/serverless" + "@kbn/serverless", + "@kbn/no-data-page-plugin" ], "exclude": ["target/**/*"] } diff --git a/src/plugins/data/common/query/text_based_query_state_to_ast.test.ts b/src/plugins/data/common/query/text_based_query_state_to_ast.test.ts index 64f9c5ca59111..ee1e072e8a50f 100644 --- a/src/plugins/data/common/query/text_based_query_state_to_ast.test.ts +++ b/src/plugins/data/common/query/text_based_query_state_to_ast.test.ts @@ -54,4 +54,30 @@ describe('textBasedQueryStateToExpressionAst', () => { }) ); }); + + it('returns an object with the correct structure for an ES|QL query', async () => { + const actual = await textBasedQueryStateToExpressionAst({ + filters: [], + query: { sql: 'FROM foo' }, + time: { + from: 'now', + to: 'now+7d', + }, + }); + + expect(actual).toHaveProperty( + 'chain.1.arguments.timeRange.0.chain.0.arguments', + expect.objectContaining({ + from: ['now'], + to: ['now+7d'], + }) + ); + + expect(actual).toHaveProperty( + 'chain.2.arguments', + expect.objectContaining({ + query: ['FROM foo'], + }) + ); + }); }); diff --git a/src/plugins/data/common/query/text_based_query_state_to_ast.ts b/src/plugins/data/common/query/text_based_query_state_to_ast.ts index cb34d9c9c405c..e24cbbd0a7dab 100644 --- a/src/plugins/data/common/query/text_based_query_state_to_ast.ts +++ b/src/plugins/data/common/query/text_based_query_state_to_ast.ts @@ -49,12 +49,13 @@ export function textBasedQueryStateToExpressionAst({ if (query && isOfAggregateQueryType(query)) { const mode = getAggregateQueryMode(query); - // sql query - if (mode === 'sql' && 'sql' in query) { - const essql = aggregateQueryToAst(query, timeFieldName); + for (const esMode of ['sql', 'esql']) { + if (mode === esMode && esMode in query) { + const essql = aggregateQueryToAst(query, timeFieldName); - if (essql) { - ast.chain.push(essql); + if (essql) { + ast.chain.push(essql); + } } } } diff --git a/src/plugins/data/common/search/expressions/aggregate_query_to_ast.test.ts b/src/plugins/data/common/search/expressions/aggregate_query_to_ast.test.ts index f292954feea82..0ded432eb0508 100644 --- a/src/plugins/data/common/search/expressions/aggregate_query_to_ast.test.ts +++ b/src/plugins/data/common/search/expressions/aggregate_query_to_ast.test.ts @@ -10,14 +10,14 @@ import { aggregateQueryToAst } from './aggregate_query_to_ast'; describe('aggregateQueryToAst', () => { it('should return a function', () => { - expect(aggregateQueryToAst({ sql: 'SELECT * from foo' })).toHaveProperty('type', 'function'); + expect(aggregateQueryToAst({ esql: 'from foo' })).toHaveProperty('type', 'function'); }); it('should forward arguments', () => { - expect(aggregateQueryToAst({ sql: 'SELECT * from foo' }, 'baz')).toHaveProperty( + expect(aggregateQueryToAst({ esql: 'from foo' }, 'baz')).toHaveProperty( 'arguments', expect.objectContaining({ - query: ['SELECT * from foo'], + query: ['from foo'], timeField: ['baz'], }) ); diff --git a/src/plugins/data/common/search/expressions/aggregate_query_to_ast.ts b/src/plugins/data/common/search/expressions/aggregate_query_to_ast.ts index 84e1e4e5f2262..6b69af873585b 100644 --- a/src/plugins/data/common/search/expressions/aggregate_query_to_ast.ts +++ b/src/plugins/data/common/search/expressions/aggregate_query_to_ast.ts @@ -5,10 +5,11 @@ * 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 { buildExpressionFunction, ExpressionAstFunction } from '@kbn/expressions-plugin/common'; import { AggregateQuery } from '../../query'; import { EssqlExpressionFunctionDefinition } from './essql'; +import { EsqlExpressionFunctionDefinition } from './esql'; export const aggregateQueryToAst = ( query: AggregateQuery, @@ -20,4 +21,11 @@ export const aggregateQueryToAst = ( timeField, }).toAst(); } + if ('esql' in query) { + return buildExpressionFunction('esql', { + query: query.esql, + timeField, + locale: i18n.getLocale(), + }).toAst(); + } }; diff --git a/src/plugins/data/common/search/expressions/esql.ts b/src/plugins/data/common/search/expressions/esql.ts new file mode 100644 index 0000000000000..8ef0f49588303 --- /dev/null +++ b/src/plugins/data/common/search/expressions/esql.ts @@ -0,0 +1,260 @@ +/* + * Copyright 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 { KibanaRequest } from '@kbn/core/server'; +import { castEsToKbnFieldTypeName, ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; +import { i18n } from '@kbn/i18n'; +import type { + Datatable, + DatatableColumnType, + ExpressionFunctionDefinition, +} from '@kbn/expressions-plugin/common'; +import { RequestAdapter } from '@kbn/inspector-plugin/common'; + +import { zipObject } from 'lodash'; +import { Observable, defer, throwError } from 'rxjs'; +import { catchError, map, switchMap, tap } from 'rxjs/operators'; +import { buildEsQuery } from '@kbn/es-query'; +import { getEsQueryConfig } from '../../es_query'; +import { getTime } from '../../query'; +import { ESQL_SEARCH_STRATEGY, IKibanaSearchRequest, ISearchGeneric, KibanaContext } from '..'; +import { IKibanaSearchResponse } from '../types'; +import { UiSettingsCommon } from '../..'; + +type Input = KibanaContext | null; +type Output = Observable; + +interface Arguments { + query: string; + timezone?: string; + timeField?: string; + locale?: string; +} + +export type EsqlExpressionFunctionDefinition = ExpressionFunctionDefinition< + 'esql', + Input, + Arguments, + Output +>; + +interface EsqlFnArguments { + getStartDependencies(getKibanaRequest: () => KibanaRequest): Promise; +} + +interface EsqlStartDependencies { + search: ISearchGeneric; + uiSettings: UiSettingsCommon; +} + +function normalizeType(type: string): DatatableColumnType { + switch (type) { + case ES_FIELD_TYPES._INDEX: + case ES_FIELD_TYPES.GEO_POINT: + case ES_FIELD_TYPES.IP: + return KBN_FIELD_TYPES.STRING; + case '_version': + return KBN_FIELD_TYPES.NUMBER; + case 'datetime': + return KBN_FIELD_TYPES.DATE; + default: + return castEsToKbnFieldTypeName(type) as DatatableColumnType; + } +} + +function sanitize(value: string) { + return value.replace(/[\(\)]/g, '_'); +} + +interface ESQLSearchParams { + time_zone?: string; + query: string; + filter?: unknown; + locale?: string; +} + +interface ESQLSearchReponse { + columns?: Array<{ + name: string; + type: string; + }>; + values: unknown[][]; +} + +export const getEsqlFn = ({ getStartDependencies }: EsqlFnArguments) => { + const essql: EsqlExpressionFunctionDefinition = { + name: 'esql', + type: 'datatable', + inputTypes: ['kibana_context', 'null'], + help: i18n.translate('data.search.esql.help', { + defaultMessage: 'Queries Elasticsearch using ES|QL.', + }), + args: { + query: { + aliases: ['_', 'q'], + types: ['string'], + help: i18n.translate('data.search.esql.query.help', { + defaultMessage: 'An ES|QL query.', + }), + }, + timezone: { + aliases: ['tz'], + types: ['string'], + default: 'UTC', + help: i18n.translate('data.search.esql.timezone.help', { + defaultMessage: + 'The timezone to use for date operations. Valid ISO8601 formats and UTC offsets both work.', + }), + }, + timeField: { + aliases: ['timeField'], + types: ['string'], + help: i18n.translate('data.search.essql.timeField.help', { + defaultMessage: 'The time field to use in the time range filter set in the context.', + }), + }, + locale: { + aliases: ['locale'], + types: ['string'], + help: i18n.translate('data.search.essql.locale.help', { + defaultMessage: 'The locale to use.', + }), + }, + }, + fn( + input, + { query, timezone, timeField, locale }, + { abortSignal, inspectorAdapters, getKibanaRequest } + ) { + return defer(() => + getStartDependencies(() => { + const request = getKibanaRequest?.(); + if (!request) { + throw new Error( + 'A KibanaRequest is required to run queries on the server. ' + + 'Please provide a request object to the expression execution params.' + ); + } + + return request; + }) + ).pipe( + switchMap(({ search, uiSettings }) => { + const params: ESQLSearchParams = { + query, + time_zone: timezone, + locale, + }; + if (input) { + const esQueryConfigs = getEsQueryConfig( + uiSettings as Parameters[0] + ); + const timeFilter = + input.timeRange && + getTime(undefined, input.timeRange, { + fieldName: timeField, + }); + + params.filter = buildEsQuery( + undefined, + input.query || [], + [...(input.filters ?? []), ...(timeFilter ? [timeFilter] : [])], + esQueryConfigs + ); + } + + let startTime = Date.now(); + const logInspectorRequest = () => { + if (!inspectorAdapters.requests) { + inspectorAdapters.requests = new RequestAdapter(); + } + + const request = inspectorAdapters.requests.start( + i18n.translate('data.search.dataRequest.title', { + defaultMessage: 'Data', + }), + { + description: i18n.translate('data.search.es_search.dataRequest.description', { + defaultMessage: + 'This request queries Elasticsearch to fetch the data for the visualization.', + }), + }, + startTime + ); + startTime = Date.now(); + + return request; + }; + + return search< + IKibanaSearchRequest, + IKibanaSearchResponse + >({ params }, { abortSignal, strategy: ESQL_SEARCH_STRATEGY }).pipe( + catchError((error) => { + if (!error.err) { + error.message = `Unexpected error from Elasticsearch: ${error.message}`; + } else { + const { type, reason } = error.err.attributes; + if (type === 'parsing_exception') { + error.message = `Couldn't parse Elasticsearch ES|QL query. You may need to add backticks to names containing special characters. Check your query and try again. Error: ${reason}`; + } else { + error.message = `Unexpected error from Elasticsearch: ${type} - ${reason}`; + } + } + + return throwError(() => error); + }), + tap({ + next({ rawResponse }) { + logInspectorRequest() + .stats({ + hits: { + label: i18n.translate('data.search.es_search.hitsLabel', { + defaultMessage: 'Hits', + }), + value: `${rawResponse.values.length}`, + description: i18n.translate('data.search.es_search.hitsDescription', { + defaultMessage: 'The number of documents returned by the query.', + }), + }, + }) + .json(params) + .ok({ json: rawResponse }); + }, + error(error) { + logInspectorRequest().error({ json: error }); + }, + }) + ); + }), + map(({ rawResponse: body, warning }) => { + const columns = + body.columns?.map(({ name, type }) => ({ + id: sanitize(name), + name: sanitize(name), + meta: { type: normalizeType(type) }, + })) ?? []; + const columnNames = columns.map(({ name }) => name); + const rows = body.values.map((row) => zipObject(columnNames, row)); + + return { + type: 'datatable', + meta: { + type: 'es_ql', + }, + columns, + rows, + warning, + } as Datatable; + }) + ); + }, + }; + + return essql; +}; diff --git a/src/plugins/data/common/search/index.ts b/src/plugins/data/common/search/index.ts index d0d103abe1ea2..50356da1a4655 100644 --- a/src/plugins/data/common/search/index.ts +++ b/src/plugins/data/common/search/index.ts @@ -18,3 +18,4 @@ export * from './strategies/es_search'; export * from './strategies/eql_search'; export * from './strategies/ese_search'; export * from './strategies/sql_search'; +export * from './strategies/esql_search'; diff --git a/src/plugins/data/common/search/search_source/search_source.test.ts b/src/plugins/data/common/search/search_source/search_source.test.ts index eeb4c5a972e3a..8ceaab7e12a18 100644 --- a/src/plugins/data/common/search/search_source/search_source.test.ts +++ b/src/plugins/data/common/search/search_source/search_source.test.ts @@ -1105,32 +1105,6 @@ describe('SearchSource', () => { expect(complete2).toBeCalledTimes(1); expect(searchSourceDependencies.search).toHaveBeenCalledTimes(1); }); - - test('should emit error on empty response', async () => { - searchSourceDependencies.search = mockSearchMethod = jest - .fn() - .mockReturnValue( - of({ rawResponse: { test: 1 }, isPartial: true, isRunning: true }, undefined) - ); - - searchSource = new SearchSource({ index: indexPattern }, searchSourceDependencies); - const options = {}; - - const next = jest.fn(); - const error = jest.fn(); - const complete = jest.fn(); - const res$ = searchSource.fetch$(options); - res$.subscribe({ next, error, complete }); - await firstValueFrom(res$).catch((_) => {}); - - expect(next).toBeCalledTimes(1); - expect(error).toBeCalledTimes(1); - expect(complete).toBeCalledTimes(0); - expect(next.mock.calls[0][0].rawResponse).toStrictEqual({ - test: 1, - }); - expect(error.mock.calls[0][0]).toBe(undefined); - }); }); describe('inspector', () => { diff --git a/src/plugins/data/common/search/search_source/search_source.ts b/src/plugins/data/common/search/search_source/search_source.ts index c11289439885b..b74b7e111b5ce 100644 --- a/src/plugins/data/common/search/search_source/search_source.ts +++ b/src/plugins/data/common/search/search_source/search_source.ts @@ -106,7 +106,6 @@ import { getRequestInspectorStats, getResponseInspectorStats } from './inspect'; import { getEsQueryConfig, IKibanaSearchResponse, - isErrorResponse, isPartialResponse, isCompleteResponse, UI_SETTINGS, @@ -547,9 +546,7 @@ export class SearchSource { // For testing timeout messages in UI, uncomment the next line // response.rawResponse.timed_out = true; return new Observable>((obs) => { - if (isErrorResponse(response)) { - obs.error(response); - } else if (isPartialResponse(response)) { + if (isPartialResponse(response)) { obs.next(this.postFlightTransform(response)); } else { if (!this.hasPostFlightRequests()) { @@ -921,8 +918,12 @@ export class SearchSource { }; body.query = buildEsQuery(index, query, filters, esQueryConfigs); - // For testing shard failure messages in UI, uncomment the next block and switch to `kibana*` data view - // body.query = { + // For testing shard failure messages in the UI, follow these steps: + // 1. Add all three sample data sets (flights, ecommerce, logs) to Kibana. + // 2. Create a data view using the index pattern `kibana*` and don't use a timestamp field. + // 3. Uncomment the lines below, navigate to Discover, + // and switch to the data view created in step 2. + // body.query.bool.must.push({ // error_query: { // indices: [ // { @@ -933,7 +934,8 @@ export class SearchSource { // }, // ], // }, - // }; + // }); + // Alternatively you could also add this query via "Edit as Query DSL", then it needs no code to be changed if (highlightAll && body.query) { body.highlight = getHighlightRequest(getConfig(UI_SETTINGS.DOC_HIGHLIGHT)); diff --git a/src/plugins/data/common/search/strategies/esql_search/index.ts b/src/plugins/data/common/search/strategies/esql_search/index.ts new file mode 100644 index 0000000000000..12594660136d8 --- /dev/null +++ b/src/plugins/data/common/search/strategies/esql_search/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 * from './types'; diff --git a/src/plugins/discover/public/application/doc/types.ts b/src/plugins/data/common/search/strategies/esql_search/types.ts similarity index 78% rename from src/plugins/discover/public/application/doc/types.ts rename to src/plugins/data/common/search/strategies/esql_search/types.ts index dd82e86cdb4b6..d71da852e55de 100644 --- a/src/plugins/discover/public/application/doc/types.ts +++ b/src/plugins/data/common/search/strategies/esql_search/types.ts @@ -6,10 +6,4 @@ * Side Public License, v 1. */ -export enum ElasticRequestState { - Loading, - NotFound, - Found, - Error, - NotFoundDataView, -} +export const ESQL_SEARCH_STRATEGY = 'esql'; diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index fadc844af4b58..e26bb07268b6d 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -33,6 +33,7 @@ const createStartContract = (): Start => { actions: { createFiltersFromValueClickAction: jest.fn().mockResolvedValue(['yes']), createFiltersFromRangeSelectAction: jest.fn(), + createFiltersFromMultiValueClickAction: jest.fn(), }, datatableUtilities: createDatatableUtilitiesMock(), search: searchServiceMock.createStartContract(), diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index a2ed53fde7704..f3679aa628560 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -34,6 +34,7 @@ import { import { createFiltersFromValueClickAction, createFiltersFromRangeSelectAction, + createFiltersFromMultiValueClickAction, createMultiValueClickActionDefinition, createValueClickActionDefinition, createSelectRangeActionDefinition, @@ -168,6 +169,7 @@ export class DataPublicPlugin actions: { createFiltersFromValueClickAction, createFiltersFromRangeSelectAction, + createFiltersFromMultiValueClickAction, }, datatableUtilities, fieldFormats, diff --git a/src/plugins/data/public/search/expressions/esql.ts b/src/plugins/data/public/search/expressions/esql.ts new file mode 100644 index 0000000000000..443d4c595c742 --- /dev/null +++ b/src/plugins/data/public/search/expressions/esql.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 and the Server Side Public License, v 1; you may 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 { StartServicesAccessor } from '@kbn/core/public'; +import { UiSettingsCommon } from '../../../common'; +import { DataPublicPluginStart, DataStartDependencies } from '../../types'; +import { getEsqlFn } from '../../../common/search/expressions/esql'; + +/** + * This is some glue code that takes in `core.getStartServices`, extracts the dependencies + * needed for this function, and wraps them behind a `getStartDependencies` function that + * is then called at runtime. + * + * We do this so that we can be explicit about exactly which dependencies the function + * requires, without cluttering up the top-level `plugin.ts` with this logic. It also + * makes testing the expression function a bit easier since `getStartDependencies` is + * the only thing you should need to mock. + * + * @param getStartServices - core's StartServicesAccessor for this plugin + * @internal + */ +export function getEsql({ + getStartServices, +}: { + getStartServices: StartServicesAccessor; +}) { + return getEsqlFn({ + async getStartDependencies() { + const [ + { uiSettings }, + , + { + nowProvider, + search: { search }, + }, + ] = await getStartServices(); + + return { nowProvider, search, uiSettings: uiSettings as unknown as UiSettingsCommon }; + }, + }); +} diff --git a/src/plugins/data/public/search/expressions/index.ts b/src/plugins/data/public/search/expressions/index.ts index cb07be49e8a62..74e947e2942bb 100644 --- a/src/plugins/data/public/search/expressions/index.ts +++ b/src/plugins/data/public/search/expressions/index.ts @@ -9,5 +9,6 @@ export * from './esaggs'; export * from './esdsl'; export * from './essql'; +export * from './esql'; export * from '../../../common/search/expressions'; export * from './eql'; diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 4a16d9487d2ea..79229eaff91bf 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -63,7 +63,7 @@ import { NowProviderInternalContract } from '../now_provider'; import { DataPublicPluginStart, DataStartDependencies } from '../types'; import { AggsService } from './aggs'; import { createUsageCollector, SearchUsageCollector } from './collectors'; -import { getEql, getEsaggs, getEsdsl, getEssql } from './expressions'; +import { getEql, getEsaggs, getEsdsl, getEssql, getEsql } from './expressions'; import { handleWarnings } from './fetch/handle_warnings'; import { ISearchInterceptor, SearchInterceptor } from './search_interceptor'; @@ -173,6 +173,11 @@ export class SearchService implements Plugin { getStartServices: StartServicesAccessor; }) ); + expressions.registerFunction( + getEsql({ getStartServices } as { + getStartServices: StartServicesAccessor; + }) + ); expressions.registerFunction( getEql({ getStartServices } as { getStartServices: StartServicesAccessor; diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index fe803b76364d8..924ddc87fb426 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -17,7 +17,11 @@ import { ScreenshotModePluginStart } from '@kbn/screenshot-mode-plugin/public'; import { SharePluginStart } from '@kbn/share-plugin/public'; import { ManagementSetup } from '@kbn/management-plugin/public'; import { DatatableUtilitiesService } from '../common'; -import { createFiltersFromRangeSelectAction, createFiltersFromValueClickAction } from './actions'; +import { + createFiltersFromMultiValueClickAction, + createFiltersFromRangeSelectAction, + createFiltersFromValueClickAction, +} from './actions'; import type { ISearchSetup, ISearchStart } from './search'; import { QuerySetup, QueryStart } from './query'; import { DataViewsContract } from './data_views'; @@ -55,6 +59,7 @@ export interface DataPublicPluginSetup { export interface DataPublicPluginStartActions { createFiltersFromValueClickAction: typeof createFiltersFromValueClickAction; createFiltersFromRangeSelectAction: typeof createFiltersFromRangeSelectAction; + createFiltersFromMultiValueClickAction: typeof createFiltersFromMultiValueClickAction; } /** diff --git a/src/plugins/data/server/search/expressions/esql.ts b/src/plugins/data/server/search/expressions/esql.ts new file mode 100644 index 0000000000000..93a4e136d88df --- /dev/null +++ b/src/plugins/data/server/search/expressions/esql.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { StartServicesAccessor } from '@kbn/core/server'; +import { DataPluginStart, DataPluginStartDependencies } from '../../plugin'; +import { getEsqlFn } from '../../../common/search/expressions/esql'; + +/** + * This is some glue code that takes in `core.getStartServices`, extracts the dependencies + * needed for this function, and wraps them behind a `getStartDependencies` function that + * is then called at runtime. + * + * We do this so that we can be explicit about exactly which dependencies the function + * requires, without cluttering up the top-level `plugin.ts` with this logic. It also + * makes testing the expression function a bit easier since `getStartDependencies` is + * the only thing you should need to mock. + * + * @param getStartServices - core's StartServicesAccessor for this plugin + * @internal + */ +export function getEsql({ + getStartServices, +}: { + getStartServices: StartServicesAccessor; +}) { + return getEsqlFn({ + getStartDependencies: async (getKibanaRequest) => { + const [{ savedObjects, uiSettings }, , { search }] = await getStartServices(); + const request = getKibanaRequest(); + const savedObjectsClient = savedObjects.getScopedClient(request); + + return { + search: search.asScoped(request).search, + uiSettings: uiSettings.asScopedToClient(savedObjectsClient), + }; + }, + }); +} diff --git a/src/plugins/data/server/search/expressions/index.ts b/src/plugins/data/server/search/expressions/index.ts index 98a08e6383f34..e9a9ff316d137 100644 --- a/src/plugins/data/server/search/expressions/index.ts +++ b/src/plugins/data/server/search/expressions/index.ts @@ -9,4 +9,5 @@ export * from './esaggs'; export * from './esdsl'; export * from './essql'; +export * from './esql'; export * from './eql'; diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts index 825b7eee3302f..f2cdc40594487 100644 --- a/src/plugins/data/server/search/index.ts +++ b/src/plugins/data/server/search/index.ts @@ -10,6 +10,7 @@ export * from './types'; export * from './strategies/es_search'; export * from './strategies/ese_search'; export * from './strategies/eql_search'; +export * from './strategies/esql_search'; export type { SearchUsage } from './collectors/search'; export { usageProvider, searchUsageObserver } from './collectors/search'; export * from './aggs'; diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index dd199403c53af..71a335ce51592 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -79,8 +79,9 @@ import { SearchSourceService, eqlRawResponse, SQL_SEARCH_STRATEGY, + ESQL_SEARCH_STRATEGY, } from '../../common/search'; -import { getEsaggs, getEsdsl, getEssql, getEql } from './expressions'; +import { getEsaggs, getEsdsl, getEssql, getEql, getEsql } from './expressions'; import { getShardDelayBucketAgg, SHARD_DELAY_AGG_NAME, @@ -95,6 +96,7 @@ import { NoSearchIdInSessionError } from './errors/no_search_id_in_session'; import { CachedUiSettingsClient } from './services'; import { sqlSearchStrategyProvider } from './strategies/sql_search'; import { searchSessionSavedObjectType } from './saved_objects'; +import { esqlSearchStrategyProvider } from './strategies/esql_search'; type StrategyMap = Record>; @@ -176,6 +178,7 @@ export class SearchService implements Plugin { usage ) ); + this.registerSearchStrategy(ESQL_SEARCH_STRATEGY, esqlSearchStrategyProvider(this.logger)); // We don't want to register this because we don't want the client to be able to access this // strategy, but we do want to expose it to other server-side plugins @@ -216,6 +219,7 @@ export class SearchService implements Plugin { expressions.registerFunction(getEsdsl({ getStartServices: core.getStartServices })); expressions.registerFunction(getEssql({ getStartServices: core.getStartServices })); expressions.registerFunction(getEql({ getStartServices: core.getStartServices })); + expressions.registerFunction(getEsql({ getStartServices: core.getStartServices })); expressions.registerFunction(cidrFunction); expressions.registerFunction(dateRangeFunction); expressions.registerFunction(extendedBoundsFunction); diff --git a/src/plugins/data/server/search/strategies/esql_search/esql_search_strategy.ts b/src/plugins/data/server/search/strategies/esql_search/esql_search_strategy.ts new file mode 100644 index 0000000000000..7f3f6f521853d --- /dev/null +++ b/src/plugins/data/server/search/strategies/esql_search/esql_search_strategy.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 { from } from 'rxjs'; +import type { Logger } from '@kbn/core/server'; +import { getKbnServerError, KbnServerError } from '@kbn/kibana-utils-plugin/server'; +import type { ISearchStrategy } from '../../types'; + +export const esqlSearchStrategyProvider = ( + logger: Logger, + useInternalUser: boolean = false +): ISearchStrategy => ({ + /** + * @param request + * @param options + * @param deps + * @throws `KbnServerError` + * @returns `Observable>` + */ + search: (request, { abortSignal, ...options }, { esClient, uiSettingsClient }) => { + // Only default index pattern type is supported here. + // See ese for other type support. + if (request.indexType) { + throw new KbnServerError(`Unsupported index pattern type ${request.indexType}`, 400); + } + + const search = async () => { + try { + const { terminateAfter, ...requestParams } = request.params ?? {}; + const { headers, body } = await esClient.asCurrentUser.transport.request( + { + method: 'POST', + path: '/_query', + body: { + ...requestParams, + }, + }, + { + signal: abortSignal, + meta: true, + } + ); + return { + rawResponse: body, + isPartial: false, + isRunning: false, + warning: headers?.warning, + }; + } catch (e) { + throw getKbnServerError(e); + } + }; + + return from(search()); + }, +}); diff --git a/src/plugins/data/server/search/strategies/esql_search/index.ts b/src/plugins/data/server/search/strategies/esql_search/index.ts new file mode 100644 index 0000000000000..14fd011acc3d8 --- /dev/null +++ b/src/plugins/data/server/search/strategies/esql_search/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 { esqlSearchStrategyProvider } from './esql_search_strategy'; 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 42614d33b660a..ad344d482c0cf 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 @@ -231,7 +231,11 @@ const IndexPatternEditorFlyoutContentComponent = ({ return ( - +

    {editData ? editorTitleEditMode : editorTitle}

    diff --git a/src/plugins/data_view_management/server/routes/resolve_index.ts b/src/plugins/data_view_management/server/routes/resolve_index.ts index 820e6de1c9d7d..c9207d020a355 100644 --- a/src/plugins/data_view_management/server/routes/resolve_index.ts +++ b/src/plugins/data_view_management/server/routes/resolve_index.ts @@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from '@kbn/core/server'; +import { getKbnServerError } from '@kbn/kibana-utils-plugin/server'; export function registerResolveIndexRoute(router: IRouter): void { router.get( @@ -32,11 +33,19 @@ export function registerResolveIndexRoute(router: IRouter): void { }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; - const body = await esClient.asCurrentUser.indices.resolveIndex({ - name: req.params.query, - expand_wildcards: req.query.expand_wildcards || 'open', - }); - return res.ok({ body }); + try { + const body = await esClient.asCurrentUser.indices.resolveIndex({ + name: req.params.query, + expand_wildcards: req.query.expand_wildcards || 'open', + }); + return res.ok({ body }); + } catch (e) { + if (e?.meta.statusCode === 404) { + return res.notFound({ body: { message: e.meta?.body?.error?.reason } }); + } else { + throw getKbnServerError(e); + } + } } ); } diff --git a/src/plugins/discover/common/constants.ts b/src/plugins/discover/common/constants.ts index 3cb696766b65f..e80f9d2449ebc 100644 --- a/src/plugins/discover/common/constants.ts +++ b/src/plugins/discover/common/constants.ts @@ -6,12 +6,18 @@ * Side Public License, v 1. */ -export const MAX_LOADED_GRID_ROWS = 10000; +import { SAMPLE_ROWS_PER_PAGE_SETTING } from '@kbn/discover-utils'; +import { IUiSettingsClient } from '@kbn/core/public'; + export const DEFAULT_ROWS_PER_PAGE = 100; export const ROWS_PER_PAGE_OPTIONS = [10, 25, 50, DEFAULT_ROWS_PER_PAGE, 250, 500]; + export enum VIEW_MODE { DOCUMENT_LEVEL = 'documents', AGGREGATED_LEVEL = 'aggregated', } export const DISABLE_SHARD_FAILURE_WARNING = true; +export const getDefaultRowsPerPage = (uiSettings: IUiSettingsClient): number => { + return parseInt(uiSettings.get(SAMPLE_ROWS_PER_PAGE_SETTING), 10) || DEFAULT_ROWS_PER_PAGE; +}; diff --git a/src/plugins/discover/common/field_types.ts b/src/plugins/discover/common/field_types.ts deleted file mode 100644 index bd24797ab5323..0000000000000 --- a/src/plugins/discover/common/field_types.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export enum KNOWN_FIELD_TYPES { - BOOLEAN = 'boolean', - CONFLICT = 'conflict', - DATE = 'date', - DATE_RANGE = 'date_range', - GEO_POINT = 'geo_point', - GEO_SHAPE = 'geo_shape', - HISTOGRAM = 'histogram', - IP = 'ip', - IP_RANGE = 'ip_range', - KEYWORD = 'keyword', - MURMUR3 = 'murmur3', - NUMBER = 'number', - NESTED = 'nested', - STRING = 'string', - TEXT = 'text', - VERSION = 'version', -} diff --git a/src/plugins/discover/kibana.jsonc b/src/plugins/discover/kibana.jsonc index 1c6ffaae833cb..0778ebf666851 100644 --- a/src/plugins/discover/kibana.jsonc +++ b/src/plugins/discover/kibana.jsonc @@ -24,9 +24,10 @@ "dataViewFieldEditor", "dataViewEditor", "expressions", + "unifiedDocViewer", "unifiedSearch", "unifiedHistogram", - "contentManagement", + "contentManagement" ], "optionalPlugins": [ "home", @@ -36,7 +37,8 @@ "triggersActionsUi", "savedObjectsTaggingOss", "lens", - "serverless" + "serverless", + "noDataPage" ], "requiredBundles": ["kibanaUtils", "kibanaReact", "unifiedSearch"], "extraPublicDirs": ["common"] diff --git a/src/plugins/discover/public/__mocks__/saved_search.ts b/src/plugins/discover/public/__mocks__/saved_search.ts index c6751b2990bc4..90a2a9c680825 100644 --- a/src/plugins/discover/public/__mocks__/saved_search.ts +++ b/src/plugins/discover/public/__mocks__/saved_search.ts @@ -27,11 +27,11 @@ export const savedSearchMockWithTimeFieldNew = { searchSource: createSearchSourceMock({ index: dataViewWithTimefieldMock }), } as unknown as SavedSearch; -export const savedSearchMockWithSQL = { - id: 'the-saved-search-id-sql', +export const savedSearchMockWithESQL = { + id: 'the-saved-search-id-esql', searchSource: createSearchSourceMock({ index: dataViewWithTimefieldMock, - query: { sql: 'SELECT * FROM "the-saved-search-id-sql"' }, + query: { esql: 'FROM "the-saved-search-id-esql"' }, }), } as unknown as SavedSearch; diff --git a/src/plugins/discover/public/application/context/context_app.tsx b/src/plugins/discover/public/application/context/context_app.tsx index 6355d6de47e80..19a5058638392 100644 --- a/src/plugins/discover/public/application/context/context_app.tsx +++ b/src/plugins/discover/public/application/context/context_app.tsx @@ -18,17 +18,20 @@ import { generateFilters } from '@kbn/data-plugin/public'; import { i18n } from '@kbn/i18n'; import { reportPerformanceMetricEvent } from '@kbn/ebt-tools'; import { removeInterceptedWarningDuplicates } from '@kbn/search-response-warnings'; -import { DOC_TABLE_LEGACY, SEARCH_FIELDS_FROM_SOURCE } from '@kbn/discover-utils'; +import { + DOC_TABLE_LEGACY, + SEARCH_FIELDS_FROM_SOURCE, + SORT_DEFAULT_ORDER_SETTING, +} from '@kbn/discover-utils'; +import { popularizeField, useColumns } from '@kbn/unified-data-table'; +import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import { ContextErrorMessage } from './components/context_error_message'; import { LoadingStatus } from './services/context_query_state'; import { AppState, GlobalState, isEqualFilters } from './services/context_state'; -import { useColumns } from '../../hooks/use_data_grid_columns'; import { useContextAppState } from './hooks/use_context_app_state'; import { useContextAppFetch } from './hooks/use_context_app_fetch'; -import { popularizeField } from '../../utils/popularize_field'; import { ContextAppContent } from './context_app_content'; import { SurrDocType } from './services/context'; -import { DocViewFilterFn } from '../../services/doc_views/doc_views_types'; import { useDiscoverServices } from '../../hooks/use_discover_services'; import { setBreadcrumbs } from '../../utils/breadcrumbs'; @@ -68,7 +71,7 @@ export const ContextApp = ({ dataView, anchorId, referrer }: ContextAppProps) => const { columns, onAddColumn, onRemoveColumn, onSetColumns } = useColumns({ capabilities, - config: uiSettings, + defaultOrder: uiSettings.get(SORT_DEFAULT_ORDER_SETTING), dataView, dataViews, useNewFieldsApi, diff --git a/src/plugins/discover/public/application/context/context_app_content.test.tsx b/src/plugins/discover/public/application/context/context_app_content.test.tsx index f7ce2235333d4..f6809d63c035d 100644 --- a/src/plugins/discover/public/application/context/context_app_content.test.tsx +++ b/src/plugins/discover/public/application/context/context_app_content.test.tsx @@ -12,11 +12,11 @@ import { findTestSubject } from '@elastic/eui/lib/test'; import { ActionBar } from './components/action_bar/action_bar'; import { GetStateReturn } from './services/context_state'; import { SortDirection } from '@kbn/data-plugin/public'; +import { UnifiedDataTable } from '@kbn/unified-data-table'; import { ContextAppContent, ContextAppContentProps } from './context_app_content'; import { LoadingStatus } from './services/context_query_state'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; import { discoverServiceMock } from '../../__mocks__/services'; -import { DiscoverGrid } from '../../components/discover_grid/discover_grid'; import { DocTableWrapper } from '../../components/doc_table/doc_table_wrapper'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { buildDataTableRecord } from '@kbn/discover-utils'; @@ -103,6 +103,6 @@ describe('ContextAppContent test', () => { it('should render discover grid correctly', async () => { const component = await mountComponent({ isLegacy: false }); - expect(component.find(DiscoverGrid).length).toBe(1); + expect(component.find(UnifiedDataTable).length).toBe(1); }); }); 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 c72b7f366e5ce..0443718be6e2b 100644 --- a/src/plugins/discover/public/application/context/context_app_content.tsx +++ b/src/plugins/discover/public/application/context/context_app_content.tsx @@ -18,18 +18,25 @@ import { type SearchResponseInterceptedWarning, SearchResponseWarnings, } from '@kbn/search-response-warnings'; -import { CONTEXT_STEP_SETTING, DOC_HIDE_TIME_COLUMN_SETTING } from '@kbn/discover-utils'; +import { + CONTEXT_STEP_SETTING, + DOC_HIDE_TIME_COLUMN_SETTING, + MAX_DOC_FIELDS_DISPLAYED, + ROW_HEIGHT_OPTION, + SHOW_MULTIFIELDS, +} from '@kbn/discover-utils'; +import { DataLoadingState, UnifiedDataTable } from '@kbn/unified-data-table'; +import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import { getDefaultRowsPerPage } from '../../../common/constants'; import { LoadingStatus } from './services/context_query_state'; import { ActionBar } from './components/action_bar/action_bar'; -import { DataLoadingState, DiscoverGrid } from '../../components/discover_grid/discover_grid'; -import { DocViewFilterFn } from '../../services/doc_views/doc_views_types'; import { AppState } from './services/context_state'; import { SurrDocType } from './services/context'; import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE } from './services/constants'; import { DocTableContext } from '../../components/doc_table/doc_table_context'; import { useDiscoverServices } from '../../hooks/use_discover_services'; -import { DiscoverGridFlyout } from '../../components/discover_grid/discover_grid_flyout'; -import { DocViewer } from '../../services/doc_views/components/doc_viewer'; +import { DiscoverGridFlyout } from '../../components/discover_grid_flyout'; +import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../../components/discover_tour'; export interface ContextAppContentProps { columns: string[]; @@ -58,7 +65,7 @@ export function clamp(value: number) { return Math.max(Math.min(MAX_CONTEXT_SIZE, value), MIN_CONTEXT_SIZE); } -const DiscoverGridMemoized = React.memo(DiscoverGrid); +const DiscoverGridMemoized = React.memo(UnifiedDataTable); const DocTableContextMemoized = React.memo(DocTableContext); const ActionBarMemoized = React.memo(ActionBar); @@ -122,6 +129,24 @@ export function ContextAppContent({ return [[dataView.timeFieldName!, SortDirection.desc]]; }, [dataView]); + const renderDocumentView = useCallback( + (hit: DataTableRecord, displayedRows: DataTableRecord[], displayedColumns: string[]) => ( + setExpandedDoc(undefined)} + setExpandedDoc={setExpandedDoc} + /> + ), + [addFilter, dataView, onAddColumn, onRemoveColumn] + ); + return ( {!!interceptedWarnings?.length && ( @@ -157,7 +182,6 @@ export function ContextAppContent({ sort={sort} useNewFieldsApi={useNewFieldsApi} dataTestSubj="contextDocTable" - DocViewer={DocViewer} /> )} {!isLegacy && ( @@ -176,14 +200,17 @@ export function ContextAppContent({ showTimeCol={showTimeCol} useNewFieldsApi={useNewFieldsApi} isPaginationEnabled={false} + rowsPerPageState={getDefaultRowsPerPage(services.uiSettings)} controlColumnIds={controlColumnIds} setExpandedDoc={setExpandedDoc} onFilter={addFilter} - onAddColumn={onAddColumn} - onRemoveColumn={onRemoveColumn} onSetColumns={onSetColumns} - DocumentView={DiscoverGridFlyout} + configRowHeight={services.uiSettings.get(ROW_HEIGHT_OPTION)} + showMultiFields={services.uiSettings.get(SHOW_MULTIFIELDS)} + maxDocFieldsDisplayed={services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED)} + renderDocumentView={renderDocumentView} services={services} + componentsTourSteps={{ expandButton: DISCOVER_TOUR_STEP_ANCHOR_IDS.expandDocument }} />
    diff --git a/src/plugins/discover/public/application/doc/components/doc.test.tsx b/src/plugins/discover/public/application/doc/components/doc.test.tsx index dc93a5718e1e0..56eac62b0318c 100644 --- a/src/plugins/discover/public/application/doc/components/doc.test.tsx +++ b/src/plugins/discover/public/application/doc/components/doc.test.tsx @@ -16,29 +16,11 @@ import { Doc, DocProps } from './doc'; import { SEARCH_FIELDS_FROM_SOURCE as mockSearchFieldsFromSource } from '@kbn/discover-utils'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { setUnifiedDocViewerServices } from '@kbn/unified-doc-viewer-plugin/public/plugin'; +import { mockUnifiedDocViewerServices } from '@kbn/unified-doc-viewer-plugin/public/__mocks__'; const mockSearchApi = jest.fn(); -jest.mock('../../../kibana_services', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let registry: any[] = []; - - return { - getDocViewsRegistry: () => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - addDocView(view: any) { - registry.push(view); - }, - getDocViewsSorted() { - return registry; - }, - resetRegistry: () => { - registry = []; - }, - }), - }; -}); - beforeEach(() => { jest.clearAllMocks(); }); @@ -86,6 +68,7 @@ async function mountDoc(update = false) { locator: { getUrl: jest.fn(() => Promise.resolve('mock-url')) }, chrome: { setBreadcrumbs: jest.fn() }, }; + setUnifiedDocViewerServices(mockUnifiedDocViewerServices); await act(async () => { comp = mountWithIntl( diff --git a/src/plugins/discover/public/application/doc/components/doc.tsx b/src/plugins/discover/public/application/doc/components/doc.tsx index 384d0d7a4ffac..83c2c08eafa2e 100644 --- a/src/plugins/discover/public/application/doc/components/doc.tsx +++ b/src/plugins/discover/public/application/doc/components/doc.tsx @@ -9,40 +9,18 @@ import React, { useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiCallOut, EuiLink, EuiLoadingSpinner, EuiPage, EuiPageBody } from '@elastic/eui'; -import type { DataView } from '@kbn/data-views-plugin/public'; import { i18n } from '@kbn/i18n'; -import type { DataTableRecord } from '@kbn/discover-utils/types'; +import { ElasticRequestState } from '@kbn/unified-doc-viewer'; +import { UnifiedDocViewer, useEsDocSearch } from '@kbn/unified-doc-viewer-plugin/public'; +import type { EsDocSearchProps } from '@kbn/unified-doc-viewer-plugin/public/types'; import { setBreadcrumbs } from '../../../utils/breadcrumbs'; -import { DocViewer } from '../../../services/doc_views/components/doc_viewer'; -import { ElasticRequestState } from '../types'; -import { useEsDocSearch } from '../../../hooks/use_es_doc_search'; import { useDiscoverServices } from '../../../hooks/use_discover_services'; -export interface DocProps { - /** - * Id of the doc in ES - */ - id: string; - /** - * Index in ES to query - */ - index: string; - /** - * DataView entity - */ - dataView: DataView; - /** - * If set, will always request source, regardless of the global `fieldsFromSource` setting - */ - requestSource?: boolean; +export interface DocProps extends EsDocSearchProps { /** * Discover main view url */ referrer?: string; - /** - * Records fetched from text based query - */ - textBasedHits?: DataTableRecord[]; } export function Doc(props: DocProps) { @@ -141,7 +119,7 @@ export function Doc(props: DocProps) { {reqState === ElasticRequestState.Found && hit !== null && dataView && (
    - +
    )} diff --git a/src/plugins/discover/public/application/main/components/layout/__stories__/discover_layout.stories.tsx b/src/plugins/discover/public/application/main/components/layout/__stories__/discover_layout.stories.tsx index 80db81bb4228b..4e143c80d96db 100644 --- a/src/plugins/discover/public/application/main/components/layout/__stories__/discover_layout.stories.tsx +++ b/src/plugins/discover/public/application/main/components/layout/__stories__/discover_layout.stories.tsx @@ -68,7 +68,7 @@ storiesOf('components/layout/DiscoverLayout', module).add( ); storiesOf('components/layout/DiscoverLayout', module).add( - 'SQL view', + 'ES|QL view', withDiscoverServices(() => { const props = getPlainRecordLayoutProps(getDataViewMock(false)); return ( diff --git a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts index 8d95db014fdc8..d681365767ce8 100644 --- a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts +++ b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts @@ -159,7 +159,7 @@ export const getPlainRecordLayoutProps = (dataView: DataView) => { columns: ['name', 'message', 'bytes'], sort: [['date', 'desc']], query: { - sql: 'SELECT * FROM "kibana_sample_data_ecommerce"', + esql: 'FROM "kibana_sample_data_ecommerce"', }, filters: [], }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx index a378d25fb04de..ec809e2c2f760 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx @@ -21,30 +21,36 @@ import { SortOrder } from '@kbn/saved-search-plugin/public'; import { CellActionsProvider } from '@kbn/cell-actions'; import type { DataTableRecord } from '@kbn/discover-utils/types'; import { SearchResponseWarnings } from '@kbn/search-response-warnings'; +import { DataLoadingState, UnifiedDataTable, useColumns } from '@kbn/unified-data-table'; import { DOC_HIDE_TIME_COLUMN_SETTING, DOC_TABLE_LEGACY, HIDE_ANNOUNCEMENTS, + MAX_DOC_FIELDS_DISPLAYED, + ROW_HEIGHT_OPTION, SAMPLE_SIZE_SETTING, SEARCH_FIELDS_FROM_SOURCE, + SHOW_MULTIFIELDS, + SORT_DEFAULT_ORDER_SETTING, } from '@kbn/discover-utils'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import { getDefaultRowsPerPage } from '../../../../../common/constants'; import { useInternalStateSelector } from '../../services/discover_internal_state_container'; import { useAppStateSelector } from '../../services/discover_app_state_container'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; -import { DocViewFilterFn } from '../../../../services/doc_views/doc_views_types'; -import { DataLoadingState, DiscoverGrid } from '../../../../components/discover_grid/discover_grid'; import { FetchStatus } from '../../../types'; -import { useColumns } from '../../../../hooks/use_data_grid_columns'; import { RecordRawType } from '../../services/discover_data_state_container'; import { DiscoverStateContainer } from '../../services/discover_state'; import { useDataState } from '../../hooks/use_data_state'; import { DocTableInfinite } from '../../../../components/doc_table/doc_table_infinite'; import { DocumentExplorerCallout } from '../document_explorer_callout'; import { DocumentExplorerUpdateCallout } from '../document_explorer_callout/document_explorer_update_callout'; -import { DiscoverTourProvider } from '../../../../components/discover_tour'; +import { + DISCOVER_TOUR_STEP_ANCHOR_IDS, + DiscoverTourProvider, +} from '../../../../components/discover_tour'; import { getRawRecordType } from '../../utils/get_raw_record_type'; -import { DiscoverGridFlyout } from '../../../../components/discover_grid/discover_grid_flyout'; -import { DocViewer } from '../../../../services/doc_views/components/doc_viewer'; +import { DiscoverGridFlyout } from '../../../../components/discover_grid_flyout'; import { useSavedSearchInitial } from '../../services/discover_state_provider'; import { useFetchMoreRecords } from './use_fetch_more_records'; @@ -57,7 +63,7 @@ const progressStyle = css` `; const DocTableInfiniteMemoized = React.memo(DocTableInfinite); -const DiscoverGridMemoized = React.memo(DiscoverGrid); +const DataGridMemoized = React.memo(UnifiedDataTable); // export needs for testing export const onResize = ( @@ -148,7 +154,7 @@ function DiscoverDocumentsComponent({ onSetColumns, } = useColumns({ capabilities, - config: uiSettings, + defaultOrder: uiSettings.get(SORT_DEFAULT_ORDER_SETTING), dataView, dataViews, setAppState: stateContainer.appState.update, @@ -185,10 +191,31 @@ function DiscoverDocumentsComponent({ const showTimeCol = useMemo( () => - !isTextBasedQuery && + // for ES|QL we want to show the time column only when is on Document view + (!isTextBasedQuery || !columns?.length) && !uiSettings.get(DOC_HIDE_TIME_COLUMN_SETTING, false) && !!dataView.timeFieldName, - [isTextBasedQuery, uiSettings, dataView.timeFieldName] + [isTextBasedQuery, columns, uiSettings, dataView.timeFieldName] + ); + + const renderDocumentView = useCallback( + (hit: DataTableRecord, displayedRows: DataTableRecord[], displayedColumns: string[]) => ( + setExpandedDoc(undefined)} + setExpandedDoc={setExpandedDoc} + query={query} + /> + ), + [dataView, onAddColumn, onAddFilter, onRemoveColumn, query, savedSearch.id, setExpandedDoc] ); if (isDataViewLoading || (isEmptyDataResult && isDataLoading)) { @@ -217,7 +244,7 @@ function DiscoverDocumentsComponent({ data-test-subj="dscInterceptedWarningsCallout" /> )} - {isLegacy && rows && rows.length && ( + {isLegacy && rows && rows.length > 0 && ( <> {!hideAnnouncements && } )} @@ -247,11 +273,11 @@ function DiscoverDocumentsComponent({ )} -
    +
    -
    )} {isDataLoading && ( - + )} ); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index 328153b6eeec5..58c23aa561e12 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -23,7 +23,13 @@ import classNames from 'classnames'; import { generateFilters } from '@kbn/data-plugin/public'; import { useDragDropContext } from '@kbn/dom-drag-drop'; import { DataViewField, DataViewType } from '@kbn/data-views-plugin/public'; -import { SEARCH_FIELDS_FROM_SOURCE, SHOW_FIELD_STATISTICS } from '@kbn/discover-utils'; +import { + SEARCH_FIELDS_FROM_SOURCE, + SHOW_FIELD_STATISTICS, + SORT_DEFAULT_ORDER_SETTING, +} from '@kbn/discover-utils'; +import { popularizeField, useColumns } from '@kbn/unified-data-table'; +import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import { useSavedSearchInitial } from '../../services/discover_state_provider'; import { DiscoverStateContainer } from '../../services/discover_state'; import { VIEW_MODE } from '../../../../../common/constants'; @@ -34,13 +40,10 @@ import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DiscoverNoResults } from '../no_results'; import { LoadingSpinner } from '../loading_spinner/loading_spinner'; import { DiscoverSidebarResponsive } from '../sidebar'; -import { popularizeField } from '../../../../utils/popularize_field'; import { DiscoverTopNav } from '../top_nav/discover_topnav'; -import { DocViewFilterFn } from '../../../../services/doc_views/doc_views_types'; import { getResultState } from '../../utils/get_result_state'; import { DiscoverUninitialized } from '../uninitialized/uninitialized'; import { DataMainMsg, RecordRawType } from '../../services/discover_data_state_container'; -import { useColumns } from '../../../../hooks/use_data_grid_columns'; import { FetchStatus } from '../../../types'; import { useDataState } from '../../hooks/use_data_state'; import { getRawRecordType } from '../../utils/get_raw_record_type'; @@ -127,7 +130,7 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { onRemoveColumn, } = useColumns({ capabilities, - config: uiSettings, + defaultOrder: uiSettings.get(SORT_DEFAULT_ORDER_SETTING), dataView, dataViews, setAppState: stateContainer.appState.update, @@ -175,6 +178,13 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { }, [isSidebarClosed, storage]); const contentCentered = resultState === 'uninitialized' || resultState === 'none'; + const documentState = useDataState(stateContainer.dataState.data$.documents$); + + const textBasedLanguageModeWarning = useMemo(() => { + if (isPlainRecord) { + return documentState.textBasedHeaderWarning; + } + }, [documentState.textBasedHeaderWarning, isPlainRecord]); const textBasedLanguageModeErrors = useMemo(() => { if (isPlainRecord) { @@ -255,6 +265,7 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { updateQuery={stateContainer.actions.onUpdateQuery} isPlainRecord={isPlainRecord} textBasedLanguageModeErrors={textBasedLanguageModeErrors} + textBasedLanguageModeWarning={textBasedLanguageModeWarning} onFieldEdited={onFieldEdited} /> diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx index 655ff5cbbb04f..91fe00263c1c4 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx @@ -12,10 +12,10 @@ import React, { useCallback } from 'react'; import { DataView } from '@kbn/data-views-plugin/common'; import { METRIC_TYPE } from '@kbn/analytics'; import { i18n } from '@kbn/i18n'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import { VIEW_MODE } from '../../../../../common/constants'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle'; -import { DocViewFilterFn } from '../../../../services/doc_views/doc_views_types'; import { DiscoverStateContainer } from '../../services/discover_state'; import { FieldStatisticsTab } from '../field_stats_table'; import { DiscoverDocuments } from './discover_documents'; diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx index e4a2a674c0f77..53e35d207507c 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.tsx @@ -25,6 +25,9 @@ import { import { createMockUnifiedHistogramApi } from '@kbn/unified-histogram-plugin/public/mocks'; import { checkHitCount, sendErrorTo } from '../../hooks/use_saved_search_messages'; import type { InspectorAdapters } from '../../hooks/use_inspector'; +import { UnifiedHistogramCustomization } from '../../../../customizations/customization_types/histogram_customization'; +import { useDiscoverCustomization } from '../../../../customizations'; +import { DiscoverCustomizationId } from '../../../../customizations/customization_service'; const mockData = dataPluginMock.createStartContract(); let mockQueryState = { @@ -71,6 +74,19 @@ jest.mock('../../hooks/use_saved_search_messages', () => { sendErrorTo: jest.fn(originalModule.sendErrorTo), }; }); +jest.mock('../../../../customizations', () => ({ + ...jest.requireActual('../../../../customizations'), + useDiscoverCustomization: jest.fn(), +})); + +let mockUseCustomizations = false; + +const mockHistogramCustomization: UnifiedHistogramCustomization = { + id: 'unified_histogram', + onFilter: jest.fn(), + onBrushEnd: jest.fn(), + withDefaultActions: true, +}; const mockCheckHitCount = checkHitCount as jest.MockedFunction; @@ -126,6 +142,23 @@ describe('useDiscoverHistogram', () => { return { hook, initialProps }; }; + beforeEach(() => { + mockUseCustomizations = false; + jest.clearAllMocks(); + + (useDiscoverCustomization as jest.Mock).mockImplementation((id: DiscoverCustomizationId) => { + if (!mockUseCustomizations) { + return undefined; + } + switch (id) { + case 'unified_histogram': + return mockHistogramCustomization; + default: + throw new Error(`Unknown customization id: ${id}`); + } + }); + }); + describe('initialization', () => { it('should return the expected parameters from getCreationOptions', async () => { const { hook } = await renderUseDiscoverHistogram(); @@ -447,4 +480,19 @@ describe('useDiscoverHistogram', () => { expect(api.refetch).toHaveBeenCalled(); }); }); + + describe('customization', () => { + test('should use custom values provided by customization fwk ', async () => { + mockUseCustomizations = true; + const stateContainer = getStateContainer(); + const { hook } = await renderUseDiscoverHistogram({ stateContainer }); + + expect(hook.result.current.onFilter).toEqual(mockHistogramCustomization.onFilter); + expect(hook.result.current.onBrushEnd).toEqual(mockHistogramCustomization.onBrushEnd); + expect(hook.result.current.withDefaultActions).toEqual( + mockHistogramCustomization.withDefaultActions + ); + expect(hook.result.current.disabledActions).toBeUndefined(); + }); + }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts index 14144634ff28c..68d821580f5a4 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts @@ -26,6 +26,7 @@ import { } from 'rxjs'; import useObservable from 'react-use/lib/useObservable'; import type { RequestAdapter } from '@kbn/inspector-plugin/common'; +import { useDiscoverCustomization } from '../../../../customizations'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { getUiActions } from '../../../../kibana_services'; import { FetchStatus } from '../../../types'; @@ -302,6 +303,8 @@ export const useDiscoverHistogram = ({ const dataView = useInternalStateSelector((state) => state.dataView!); + const histogramCustomization = useDiscoverCustomization('unified_histogram'); + return { ref, getCreationOptions, @@ -312,6 +315,10 @@ export const useDiscoverHistogram = ({ timeRange, relativeTimeRange, columns, + onFilter: histogramCustomization?.onFilter, + onBrushEnd: histogramCustomization?.onBrushEnd, + withDefaultActions: histogramCustomization?.withDefaultActions, + disabledActions: histogramCustomization?.disabledActions, }; }; diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx index 6be8266691089..1f8ffa8b655ce 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -497,7 +497,7 @@ describe('discover responsive sidebar', function () { expect(findTestSubject(comp, 'dataView-add-field_btn').length).toBe(1); }); - it('should render correctly in the sql mode', async () => { + it('should render correctly in the ES|QL mode', async () => { const propsWithTextBasedMode = { ...props, columns: ['extension', 'bytes'], @@ -514,7 +514,7 @@ describe('discover responsive sidebar', function () { }) as DataDocuments$, }; const compInTextBasedMode = await mountComponent(propsWithTextBasedMode, { - query: { sql: 'SELECT * FROM `index`' }, + query: { esql: 'FROM `index`' }, }); await act(async () => { diff --git a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx index 66f566cff1673..a743d4c1abebd 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx @@ -9,7 +9,7 @@ import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import type { Query, TimeRange, AggregateQuery } from '@kbn/es-query'; import { DataViewType, type DataView } from '@kbn/data-views-plugin/public'; import type { DataViewPickerProps } from '@kbn/unified-search-plugin/public'; -import { ENABLE_SQL } from '@kbn/discover-utils'; +import { ENABLE_ESQL } from '@kbn/discover-utils'; import { useSavedSearchInitial } from '../../services/discover_state_provider'; import { useInternalStateSelector } from '../../services/discover_internal_state_container'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; @@ -31,6 +31,7 @@ export interface DiscoverTopNavProps { stateContainer: DiscoverStateContainer; isPlainRecord: boolean; textBasedLanguageModeErrors?: Error; + textBasedLanguageModeWarning?: string; onFieldEdited: () => Promise; } @@ -42,6 +43,7 @@ export const DiscoverTopNav = ({ updateQuery, isPlainRecord, textBasedLanguageModeErrors, + textBasedLanguageModeWarning, onFieldEdited, }: DiscoverTopNavProps) => { const adHocDataViews = useInternalStateSelector((state) => state.adHocDataViews); @@ -164,10 +166,10 @@ export const DiscoverTopNav = ({ const setMenuMountPoint = useMemo(() => { return getHeaderActionMenuMounter(); }, []); - const isSQLModeEnabled = uiSettings.get(ENABLE_SQL); + const isESQLModeEnabled = uiSettings.get(ENABLE_ESQL); const supportedTextBasedLanguages = []; - if (isSQLModeEnabled) { - supportedTextBasedLanguages.push('SQL'); + if (isESQLModeEnabled) { + supportedTextBasedLanguages.push('ESQL'); } const dataViewPickerProps: DataViewPickerProps = { trigger: { @@ -233,6 +235,7 @@ export const DiscoverTopNav = ({ textBasedLanguageModeErrors={ textBasedLanguageModeErrors ? [textBasedLanguageModeErrors] : undefined } + textBasedLanguageModeWarning={textBasedLanguageModeWarning} onTextBasedSavedAndExit={onTextBasedSavedAndExit} prependFilterBar={ searchBarCustomization?.PrependFilterBar ? ( diff --git a/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.test.ts b/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.test.ts index 44cf4c503be30..4e3e7068f883d 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.test.ts +++ b/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.test.ts @@ -74,7 +74,7 @@ test('getTopNavLinks result', () => { `); }); -test('getTopNavLinks result for sql mode', () => { +test('getTopNavLinks result for ES|QL mode', () => { const topNavLinks = getTopNavLinks({ dataView: dataViewMock, onOpenInspector: jest.fn(), diff --git a/src/plugins/discover/public/application/main/discover_main_route.tsx b/src/plugins/discover/public/application/main/discover_main_route.tsx index cf62f96ca7d1a..bd8a5d3454602 100644 --- a/src/plugins/discover/public/application/main/discover_main_route.tsx +++ b/src/plugins/discover/public/application/main/discover_main_route.tsx @@ -48,11 +48,7 @@ export interface MainRouteProps { mode?: DiscoverDisplayMode; } -export function DiscoverMainRoute({ - customizationCallbacks, - isDev, - mode = 'standalone', -}: MainRouteProps) { +export function DiscoverMainRoute({ customizationCallbacks, mode = 'standalone' }: MainRouteProps) { const history = useHistory(); const services = useDiscoverServices(); const { @@ -64,10 +60,12 @@ export function DiscoverMainRoute({ dataViewEditor, } = services; const { id: savedSearchId } = useParams(); + const stateContainer = useSingleton(() => getDiscoverStateContainer({ history, services, + mode, }) ); const { customizationService, isInitialized: isCustomizationServiceInitialized } = @@ -109,7 +107,7 @@ export function DiscoverMainRoute({ const hasUserDataViewValue = await data.dataViews.hasData .hasUserDataView() .catch(() => false); - const hasESDataValue = isDev || (await data.dataViews.hasData.hasESData().catch(() => false)); + const hasESDataValue = await data.dataViews.hasData.hasESData().catch(() => false); setHasUserDataView(hasUserDataViewValue); setHasESData(hasESDataValue); @@ -134,7 +132,7 @@ export function DiscoverMainRoute({ setError(e); return false; } - }, [data.dataViews, isDev, savedSearchId]); + }, [data.dataViews, savedSearchId]); const loadSavedSearch = useCallback( async (nextDataView?: DataView) => { @@ -256,11 +254,12 @@ export function DiscoverMainRoute({ // We've already called this, so we can optimize the analytics services to // use the already-retrieved data to avoid a double-call. - hasESData: () => Promise.resolve(isDev ? true : hasESData), + hasESData: () => Promise.resolve(hasESData), hasUserDataView: () => Promise.resolve(hasUserDataView), }, }, dataViewEditor, + noDataPage: services.noDataPage, }; return ( diff --git a/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.tsx b/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.tsx index 125d47c087640..edacd4ba3976e 100644 --- a/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.tsx +++ b/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.tsx @@ -50,7 +50,7 @@ function getHookProps( replaceUrlState, }; } -const query = { sql: 'SELECT * from the-data-view-title' }; +const query = { esql: 'from the-data-view-title' }; const msgComplete = { recordRawType: RecordRawType.PLAIN, fetchStatus: FetchStatus.PARTIAL, @@ -103,19 +103,16 @@ describe('useTextBasedQueryLanguage', () => { const { replaceUrlState, stateContainer } = renderHookWithContext(true); await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); - expect(replaceUrlState).toHaveBeenCalledWith({ index: 'the-data-view-id' }); - - replaceUrlState.mockReset(); - - stateContainer.dataState.data$.documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); - await waitFor(() => { expect(replaceUrlState).toHaveBeenCalledWith({ index: 'the-data-view-id', - columns: ['field1', 'field2'], }); }); + + replaceUrlState.mockReset(); + + stateContainer.dataState.data$.documents$.next(msgComplete); + expect(replaceUrlState).toHaveBeenCalledTimes(0); }); test('should change viewMode to DOCUMENT_LEVEL if it was AGGREGATED_LEVEL', async () => { const { replaceUrlState } = renderHookWithContext(false, { @@ -132,7 +129,7 @@ describe('useTextBasedQueryLanguage', () => { const { replaceUrlState, stateContainer } = renderHookWithContext(false); const documents$ = stateContainer.dataState.data$.documents$; stateContainer.dataState.data$.documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); replaceUrlState.mockReset(); documents$.next({ @@ -145,7 +142,7 @@ describe('useTextBasedQueryLanguage', () => { flattened: { field1: 1 }, } as unknown as DataTableRecord, ], - query: { sql: 'SELECT field1 from the-data-view-title' }, + query: { esql: 'from the-data-view-title | keep field1' }, }); await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); @@ -162,7 +159,7 @@ describe('useTextBasedQueryLanguage', () => { const documents$ = stateContainer.dataState.data$.documents$; documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); replaceUrlState.mockReset(); documents$.next({ @@ -175,7 +172,7 @@ describe('useTextBasedQueryLanguage', () => { flattened: { field1: 1 }, } as unknown as DataTableRecord, ], - query: { sql: 'SELECT field1 from the-data-view-title' }, + query: { esql: 'from the-data-view-title | keep field1' }, }); await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); replaceUrlState.mockReset(); @@ -190,17 +187,17 @@ describe('useTextBasedQueryLanguage', () => { flattened: { field1: 1 }, } as unknown as DataTableRecord, ], - query: { sql: 'SELECT field1 from the-data-view-title WHERE field1=1' }, + query: { esql: 'from the-data-view-title | keep field 1 | WHERE field1=1' }, }); - await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(0)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); }); test('if its not a text based query coming along, it should be ignored', async () => { const { replaceUrlState, stateContainer } = renderHookWithContext(false); const documents$ = stateContainer.dataState.data$.documents$; documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); replaceUrlState.mockReset(); documents$.next({ @@ -225,7 +222,7 @@ describe('useTextBasedQueryLanguage', () => { flattened: { field1: 1 }, } as unknown as DataTableRecord, ], - query: { sql: 'SELECT field1 from the-data-view-title WHERE field1=1' }, + query: { esql: 'from the-data-view-title | keep field 1 | WHERE field1=1' }, }); await waitFor(() => { @@ -253,7 +250,7 @@ describe('useTextBasedQueryLanguage', () => { flattened: { field1: 1 }, } as unknown as DataTableRecord, ], - query: { sql: 'SELECT field1 from the-data-view-title WHERE field1=1' }, + query: { esql: 'from the-data-view-title | keep field 1 | WHERE field1=1' }, }); documents$.next({ @@ -266,9 +263,9 @@ describe('useTextBasedQueryLanguage', () => { flattened: { field1: 1 }, } as unknown as DataTableRecord, ], - query: { sql: 'SELECT field1 from the-data-view-title' }, + query: { esql: 'from the-data-view-title | keep field1' }, }); - await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); expect(replaceUrlState).toHaveBeenCalledWith({ columns: ['field1'], }); @@ -284,9 +281,9 @@ describe('useTextBasedQueryLanguage', () => { documents$.next({ recordRawType: RecordRawType.PLAIN, fetchStatus: FetchStatus.LOADING, - query: { sql: 'SELECT * from the-data-view-title WHERE field1=2' }, + query: { esql: 'from the-data-view-title | WHERE field1=2' }, }); - await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); + expect(replaceUrlState).toHaveBeenCalledTimes(0); documents$.next({ recordRawType: RecordRawType.PLAIN, fetchStatus: FetchStatus.PARTIAL, @@ -297,9 +294,9 @@ describe('useTextBasedQueryLanguage', () => { flattened: { field1: 1 }, } as unknown as DataTableRecord, ], - query: { sql: 'SELECT * from the-data-view-title WHERE field1=2' }, + query: { esql: 'from the-data-view-title | WHERE field1=2' }, }); - await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + expect(replaceUrlState).toHaveBeenCalledTimes(0); stateContainer.appState.getState = jest.fn(() => { return { columns: ['field1', 'field2'], index: 'the-data-view-id' }; }); @@ -308,7 +305,7 @@ describe('useTextBasedQueryLanguage', () => { documents$.next({ recordRawType: RecordRawType.PLAIN, fetchStatus: FetchStatus.LOADING, - query: { sql: 'SELECT field1; from the-data-view-title WHERE field1=2' }, + query: { esql: 'from the-data-view-title | keep field 1; | WHERE field1=2' }, }); documents$.next({ @@ -319,7 +316,7 @@ describe('useTextBasedQueryLanguage', () => { documents$.next({ recordRawType: RecordRawType.PLAIN, fetchStatus: FetchStatus.LOADING, - query: { sql: 'SELECT field1 from the-data-view-title' }, + query: { esql: 'from the-data-view-title | keep field1' }, }); documents$.next({ @@ -332,7 +329,7 @@ describe('useTextBasedQueryLanguage', () => { flattened: { field1: 1 }, } as unknown as DataTableRecord, ], - query: { sql: 'SELECT field1 from the-data-view-title' }, + query: { esql: 'from the-data-view-title | keep field1' }, }); await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); @@ -350,7 +347,7 @@ describe('useTextBasedQueryLanguage', () => { renderHook(() => useTextBasedQueryLanguage(props), { wrapper: getHookContext(stateContainer) }); documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); replaceUrlState.mockReset(); documents$.next({ @@ -363,7 +360,7 @@ describe('useTextBasedQueryLanguage', () => { flattened: { field1: 1 }, } as unknown as DataTableRecord, ], - query: { sql: 'SELECT field1 from the-data-view-*' }, + query: { esql: 'from the-data-view-* | keep field1' }, }); props.stateContainer.actions.setDataView(dataViewAdHoc); await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); diff --git a/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts b/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts index 4939049ceedda..fb3725d12b1e1 100644 --- a/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts +++ b/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts @@ -6,12 +6,7 @@ * Side Public License, v 1. */ import { isEqual } from 'lodash'; -import { - isOfAggregateQueryType, - getIndexPatternFromSQLQuery, - AggregateQuery, - Query, -} from '@kbn/es-query'; +import { isOfAggregateQueryType, getAggregateQueryMode } from '@kbn/es-query'; import { useCallback, useEffect, useRef } from 'react'; import type { DataViewsContract } from '@kbn/data-views-plugin/public'; import { VIEW_MODE } from '@kbn/saved-search-plugin/public'; @@ -21,6 +16,8 @@ import { getValidViewMode } from '../utils/get_valid_view_mode'; import { FetchStatus } from '../../types'; const MAX_NUM_OF_COLUMNS = 50; +// For ES|QL we want in case of the following commands to display a table view, otherwise display a document view +const TRANSFORMATIONAL_COMMANDS = ['stats', 'project', 'keep']; /** * Hook to take care of text based query language state transformations when a new result is returned @@ -33,11 +30,14 @@ export function useTextBasedQueryLanguage({ stateContainer: DiscoverStateContainer; dataViews: DataViewsContract; }) { - const prev = useRef<{ query: AggregateQuery | Query | undefined; columns: string[] }>({ + const prev = useRef<{ + query: string; + columns: string[]; + }>({ columns: [], - query: undefined, + query: '', }); - const indexTitle = useRef(''); + const initialFetch = useRef(true); const savedSearch = useSavedSearchInitial(); const cleanup = useCallback(() => { @@ -45,9 +45,8 @@ export function useTextBasedQueryLanguage({ // cleanup when it's not a text based query lang prev.current = { columns: [], - query: undefined, + query: '', }; - indexTitle.current = ''; } }, []); @@ -63,51 +62,60 @@ export function useTextBasedQueryLanguage({ fetchStatus: FetchStatus.COMPLETE, }); }; - const { columns: stateColumns, index, viewMode } = stateContainer.appState.getState(); + const { index, viewMode } = stateContainer.appState.getState(); let nextColumns: string[] = []; const isTextBasedQueryLang = - recordRawType === 'plain' && isOfAggregateQueryType(query) && 'sql' in query; + recordRawType === 'plain' && + isOfAggregateQueryType(query) && + ('sql' in query || 'esql' in query); const hasResults = Boolean(next.result?.length); - const initialFetch = !prev.current.columns.length; + let queryHasTransformationalCommands = 'sql' in query; + if ('esql' in query) { + TRANSFORMATIONAL_COMMANDS.forEach((command: string) => { + if (query.esql.toLowerCase().includes(command)) { + queryHasTransformationalCommands = true; + return; + } + }); + } if (isTextBasedQueryLang) { + const language = getAggregateQueryMode(query); if (next.fetchStatus !== FetchStatus.PARTIAL) { return; } + const dataViewObj = stateContainer.internalState.getState().dataView!; + if (hasResults) { // check if state needs to contain column transformation due to a different columns in the resultset const firstRow = next.result![0]; const firstRowColumns = Object.keys(firstRow.raw).slice(0, MAX_NUM_OF_COLUMNS); - if ( - !isEqual(firstRowColumns, prev.current.columns) && - !isEqual(query, prev.current.query) - ) { - prev.current = { columns: firstRowColumns, query }; + if (!queryHasTransformationalCommands) { + nextColumns = []; + initialFetch.current = false; + } else { nextColumns = firstRowColumns; - } - - if (firstRowColumns && initialFetch) { - prev.current = { columns: firstRowColumns, query }; + if ( + initialFetch.current && + !prev.current.columns.length && + Boolean(dataViewObj?.id === index) + ) { + prev.current.columns = firstRowColumns; + } } } - const indexPatternFromQuery = getIndexPatternFromSQLQuery(query.sql); - - const dataViewObj = stateContainer.internalState.getState().dataView!; - - // don't set the columns on initial fetch, to prevent overwriting existing state - const addColumnsToState = Boolean( - nextColumns.length && (!initialFetch || !stateColumns?.length) - ); + const addColumnsToState = !isEqual(nextColumns, prev.current.columns); + const queryChanged = query[language] !== prev.current.query; // no need to reset index to state if it hasn't changed - const addDataViewToState = Boolean(dataViewObj?.id !== index) || initialFetch; - const queryChanged = indexPatternFromQuery !== indexTitle.current; - if (!addColumnsToState && !queryChanged) { + const addDataViewToState = Boolean(dataViewObj?.id !== index); + if (!queryChanged || (!addDataViewToState && !addColumnsToState)) { sendComplete(); return; } if (queryChanged) { - indexTitle.current = indexPatternFromQuery; + prev.current.query = query[language]; + prev.current.columns = nextColumns; } const nextState = { ...(addDataViewToState && { index: dataViewObj.id }), diff --git a/src/plugins/discover/public/application/main/services/discover_app_state_container.ts b/src/plugins/discover/public/application/main/services/discover_app_state_container.ts index ea2d1d1f2324a..47cd216b1547e 100644 --- a/src/plugins/discover/public/application/main/services/discover_app_state_container.ts +++ b/src/plugins/discover/public/application/main/services/discover_app_state_container.ts @@ -23,12 +23,12 @@ import { SavedSearch, VIEW_MODE } from '@kbn/saved-search-plugin/public'; import { IKbnUrlStateStorage, ISyncStateRef, syncState } from '@kbn/kibana-utils-plugin/public'; import { isEqual } from 'lodash'; import { connectToQueryState, syncGlobalQueryStateWithUrl } from '@kbn/data-plugin/public'; +import type { UnifiedDataTableSettings } from '@kbn/unified-data-table'; import type { DiscoverServices } from '../../../build_services'; import { addLog } from '../../../utils/add_log'; import { cleanupUrlState } from '../utils/cleanup_url_state'; import { getStateDefaults } from '../utils/get_state_defaults'; import { handleSourceColumnState } from '../../../utils/state_helpers'; -import type { DiscoverGridSettings } from '../../../components/discover_grid/types'; export const APP_STATE_URL_KEY = '_a'; export interface DiscoverAppStateContainer extends ReduxLikeStateContainer { @@ -87,7 +87,7 @@ export interface DiscoverAppState { /** * Data Grid related state */ - grid?: DiscoverGridSettings; + grid?: UnifiedDataTableSettings; /** * Hide chart */ diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts index d3f600dcfaff8..516d81cc9c3f0 100644 --- a/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.test.ts @@ -10,7 +10,7 @@ import { waitFor } from '@testing-library/react'; import { buildDataTableRecord } from '@kbn/discover-utils'; import { dataViewMock, esHitsMockWithSort } from '@kbn/discover-utils/src/__mocks__'; import { discoverServiceMock } from '../../../__mocks__/services'; -import { savedSearchMockWithSQL } from '../../../__mocks__/saved_search'; +import { savedSearchMockWithESQL } from '../../../__mocks__/saved_search'; import { FetchStatus } from '../../types'; import { setUrlTracker } from '../../../kibana_services'; import { urlTrackerMock } from '../../../__mocks__/url_tracker.mock'; @@ -104,10 +104,10 @@ describe('test getDataStateContainer', () => { test('useSavedSearch returns plain record raw type', async () => { const stateContainer = getDiscoverStateMock({ - savedSearch: savedSearchMockWithSQL, + savedSearch: savedSearchMockWithESQL, }); - stateContainer.savedSearchState.load = jest.fn().mockResolvedValue(savedSearchMockWithSQL); - await stateContainer.actions.loadSavedSearch({ savedSearchId: savedSearchMockWithSQL.id }); + stateContainer.savedSearchState.load = jest.fn().mockResolvedValue(savedSearchMockWithESQL); + await stateContainer.actions.loadSavedSearch({ savedSearchId: savedSearchMockWithESQL.id }); expect(stateContainer.dataState.data$.main$.getValue().recordRawType).toBe(RecordRawType.PLAIN); }); diff --git a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts index f243d9884ca9e..417fa6679501b 100644 --- a/src/plugins/discover/public/application/main/services/discover_data_state_container.ts +++ b/src/plugins/discover/public/application/main/services/discover_data_state_container.ts @@ -57,7 +57,7 @@ export enum RecordRawType { */ DOCUMENT = 'document', /** - * Data returned e.g. SQL queries, flat structure + * Data returned e.g. ES|QL queries, flat structure * */ PLAIN = 'plain', } @@ -78,6 +78,7 @@ export interface DataMainMsg extends DataMsg { export interface DataDocumentsMsg extends DataMsg { result?: DataTableRecord[]; textBasedQueryColumns?: DatatableColumn[]; // columns from text-based request + textBasedHeaderWarning?: string; interceptedWarnings?: SearchResponseInterceptedWarning[]; // warnings (like shard failures) } 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 6533fd74c1fce..bcd96315ce575 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 @@ -468,8 +468,8 @@ describe('Test discover state actions', () => { ); }); - test('loadSavedSearch without id containing sql, adding no warning toast with an invalid index', async () => { - const url = "/#?_a=(index:abcde,query:(sql:'Select * from test'))&_g=()"; + test('loadSavedSearch without id containing ES|QL, adding no warning toast with an invalid index', async () => { + const url = "/#?_a=(index:abcde,query:(esql:'FROM test'))&_g=()"; const { state } = await getState(url, { savedSearch: savedSearchMock, isEmptyUrl: false }); await state.actions.loadSavedSearch(); expect(discoverServiceMock.toastNotifications.addWarning).not.toHaveBeenCalled(); @@ -737,3 +737,43 @@ describe('Test discover state actions', () => { expect(setRefreshInterval).toHaveBeenCalledWith({ pause: false, value: 1000 }); }); }); + +describe('Test discover state with embedded mode', () => { + let stopSync = () => {}; + let history: History; + let state: DiscoverStateContainer; + const getCurrentUrl = () => history.createHref(history.location); + + beforeEach(async () => { + history = createBrowserHistory(); + history.push('/'); + state = getDiscoverStateContainer({ + services: discoverServiceMock, + history, + mode: 'embedded', + }); + state.savedSearchState.set(savedSearchMock); + await state.appState.update({}, true); + stopSync = startSync(state.appState); + }); + afterEach(() => { + stopSync(); + stopSync = () => {}; + }); + test('setting app state and syncing to URL', async () => { + state.appState.update({ index: 'modified' }); + await new Promise(process.nextTick); + expect(getCurrentUrl()).toMatchInlineSnapshot( + `"/?_a=(columns:!(default_column),index:modified,interval:auto,sort:!())"` + ); + }); + + test('changing URL to be propagated to appState', async () => { + history.push('/?_a=(index:modified)'); + expect(state.appState.getState()).toMatchObject( + expect.objectContaining({ + index: 'modified', + }) + ); + }); +}); diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts index 1a34f097f3f4e..d6e2809c14bd6 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -26,7 +26,7 @@ import { merge } from 'rxjs'; import { AggregateQuery, Query, TimeRange } from '@kbn/es-query'; import { loadSavedSearch as loadSavedSearchFn } from './load_saved_search'; import { restoreStateFromSavedSearch } from '../../../services/saved_searches/restore_from_saved_search'; -import { FetchStatus } from '../../types'; +import { DiscoverDisplayMode, FetchStatus } from '../../types'; import { changeDataView } from '../hooks/utils/change_data_view'; import { buildStateSubscribe } from '../hooks/utils/build_state_subscribe'; import { addLog } from '../../../utils/add_log'; @@ -64,6 +64,11 @@ interface DiscoverStateContainerParams { * core ui settings service */ services: DiscoverServices; + /* + * mode in which discover is running + * + * */ + mode?: DiscoverDisplayMode; } export interface LoadParams { @@ -188,6 +193,7 @@ export interface DiscoverStateContainer { export function getDiscoverStateContainer({ history, services, + mode = 'standalone', }: DiscoverStateContainerParams): DiscoverStateContainer { const storeInSessionStorage = services.uiSettings.get('state:storeInSessionStorage'); const toasts = services.core.notifications.toasts; @@ -198,6 +204,7 @@ export function getDiscoverStateContainer({ const stateStorage = createKbnUrlStateStorage({ useHash: storeInSessionStorage, history, + useHashQuery: mode !== 'embedded', ...(toasts && withNotifyOnErrors(toasts)), }); diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts index 7f19ec3a23695..ba8a09e17e3d1 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts @@ -22,7 +22,7 @@ import { SavedSearchData, } from '../services/discover_data_state_container'; import { fetchDocuments } from './fetch_documents'; -import { fetchSql } from './fetch_sql'; +import { fetchTextBased } from './fetch_text_based'; import { buildDataTableRecord } from '@kbn/discover-utils'; import { dataViewMock, esHitsMockWithSort } from '@kbn/discover-utils/src/__mocks__'; import { searchResponseWarningsMock } from '@kbn/search-response-warnings/src/__mocks__/search_response_warnings'; @@ -31,12 +31,12 @@ jest.mock('./fetch_documents', () => ({ fetchDocuments: jest.fn().mockResolvedValue([]), })); -jest.mock('./fetch_sql', () => ({ - fetchSql: jest.fn().mockResolvedValue([]), +jest.mock('./fetch_text_based', () => ({ + fetchTextBased: jest.fn().mockResolvedValue([]), })); const mockFetchDocuments = fetchDocuments as unknown as jest.MockedFunction; -const mockFetchSQL = fetchSql as unknown as jest.MockedFunction; +const mockfetchTextBased = fetchTextBased as unknown as jest.MockedFunction; function subjectCollector(subject: Subject): () => Promise { const promise = firstValueFrom( @@ -88,7 +88,7 @@ describe('test fetchAll', () => { }; mockFetchDocuments.mockReset().mockResolvedValue({ records: [] }); - mockFetchSQL.mockReset().mockResolvedValue({ records: [] }); + mockfetchTextBased.mockReset().mockResolvedValue({ records: [] }); }); test('changes of fetchStatus when starting with FetchStatus.UNINITIALIZED', async () => { @@ -246,18 +246,18 @@ describe('test fetchAll', () => { ]); }); - test('emits loading and documents on documents$ correctly for SQL query', async () => { + test('emits loading and documents on documents$ correctly for ES|QL query', async () => { const collect = subjectCollector(subjects.documents$); const hits = [ { _id: '1', _index: 'logs' }, { _id: '2', _index: 'logs' }, ]; const documents = hits.map((hit) => buildDataTableRecord(hit, dataViewMock)); - mockFetchSQL.mockResolvedValue({ + mockfetchTextBased.mockResolvedValue({ records: documents, textBasedQueryColumns: [{ id: '1', name: 'test1', meta: { type: 'number' } }], }); - const query = { sql: 'SELECT * from foo' }; + const query = { esql: 'from foo' }; deps = { abortController: new AbortController(), inspectorAdapters: { requests: new RequestAdapter() }, diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.ts b/src/plugins/discover/public/application/main/utils/fetch_all.ts index bf2bc0c1eb1b0..ff754b065a130 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.ts @@ -27,7 +27,7 @@ import { fetchDocuments } from './fetch_documents'; import { FetchStatus } from '../../types'; import { DataMsg, RecordRawType, SavedSearchData } from '../services/discover_data_state_container'; import { DiscoverServices } from '../../../build_services'; -import { fetchSql } from './fetch_sql'; +import { fetchTextBased } from './fetch_text_based'; import { InternalState } from '../services/discover_internal_state_container'; export interface FetchDeps { @@ -70,10 +70,10 @@ export function fetchAll( const query = getAppState().query; const prevQuery = dataSubjects.documents$.getValue().query; const recordRawType = getRawRecordType(query); + const useTextbased = recordRawType === RecordRawType.PLAIN; if (reset) { sendResetMsg(dataSubjects, initialFetchStatus, recordRawType); } - const useSql = recordRawType === RecordRawType.PLAIN; if (recordRawType === RecordRawType.DOCUMENT) { // Update the base searchSource, base for all child fetches @@ -92,14 +92,14 @@ export function fetchAll( // Start fetching all required requests const response = - useSql && query - ? fetchSql(query, dataView, data, services.expressions, inspectorAdapters) + useTextbased && query + ? fetchTextBased(query, dataView, data, services.expressions, inspectorAdapters) : fetchDocuments(searchSource, fetchDeps); - const fetchType = useSql && query ? 'fetchSql' : 'fetchDocuments'; + const fetchType = useTextbased && query ? 'fetchTextBased' : 'fetchDocuments'; const startTime = window.performance.now(); // Handle results of the individual queries and forward the results to the corresponding dataSubjects response - .then(({ records, textBasedQueryColumns, interceptedWarnings }) => { + .then(({ records, textBasedQueryColumns, interceptedWarnings, textBasedHeaderWarning }) => { if (services.analytics) { const duration = window.performance.now() - startTime; reportPerformanceMetricEvent(services.analytics, { @@ -125,7 +125,7 @@ export function fetchAll( * So it takes too long, a bad user experience, also a potential flakniess in tests */ const fetchStatus = - useSql && (!prevQuery || !isEqual(query, prevQuery)) + useTextbased && (!prevQuery || !isEqual(query, prevQuery)) ? FetchStatus.PARTIAL : FetchStatus.COMPLETE; @@ -133,6 +133,7 @@ export function fetchAll( fetchStatus, result: records, textBasedQueryColumns, + textBasedHeaderWarning, interceptedWarnings, recordRawType, query, diff --git a/src/plugins/discover/public/application/main/utils/fetch_documents.ts b/src/plugins/discover/public/application/main/utils/fetch_documents.ts index 767163259304f..892da705f4b8f 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_documents.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_documents.ts @@ -12,7 +12,7 @@ import { isCompleteResponse, ISearchSource } from '@kbn/data-plugin/public'; import { SAMPLE_SIZE_SETTING, buildDataTableRecordList } from '@kbn/discover-utils'; import type { EsHitRecord } from '@kbn/discover-utils/types'; import { getSearchResponseInterceptedWarnings } from '@kbn/search-response-warnings'; -import type { RecordsFetchResponse } from '../../../types'; +import type { RecordsFetchResponse } from '../../types'; import { DISABLE_SHARD_FAILURE_WARNING } from '../../../../common/constants'; import { FetchDeps } from './fetch_all'; diff --git a/src/plugins/discover/public/application/main/utils/fetch_sql.ts b/src/plugins/discover/public/application/main/utils/fetch_text_based.ts similarity index 87% rename from src/plugins/discover/public/application/main/utils/fetch_sql.ts rename to src/plugins/discover/public/application/main/utils/fetch_text_based.ts index 73c716e8f9351..6a164bfd8a5f8 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_sql.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_text_based.ts @@ -15,16 +15,16 @@ import type { Datatable } from '@kbn/expressions-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/common'; import { textBasedQueryStateToAstWithValidation } from '@kbn/data-plugin/common'; import type { DataTableRecord } from '@kbn/discover-utils/types'; -import { RecordsFetchResponse } from '../../../types'; +import type { RecordsFetchResponse } from '../../types'; -interface SQLErrorResponse { +interface TextBasedErrorResponse { error: { message: string; }; type: 'error'; } -export function fetchSql( +export function fetchTextBased( query: Query | AggregateQuery, dataView: DataView, data: DataPublicPluginStart, @@ -49,14 +49,16 @@ export function fetchSql( let finalData: DataTableRecord[] = []; let textBasedQueryColumns: Datatable['columns'] | undefined; let error: string | undefined; + let textBasedHeaderWarning: string | undefined; execution.pipe(pluck('result')).subscribe((resp) => { - const response = resp as Datatable | SQLErrorResponse; + const response = resp as Datatable | TextBasedErrorResponse; if (response.type === 'error') { error = response.error.message; } else { const table = response as Datatable; const rows = table?.rows ?? []; textBasedQueryColumns = table?.columns ?? undefined; + textBasedHeaderWarning = table.warning ?? undefined; finalData = rows.map( (row: Record, idx: number) => ({ @@ -74,6 +76,7 @@ export function fetchSql( return { records: finalData || [], textBasedQueryColumns, + textBasedHeaderWarning, }; } }); @@ -81,6 +84,7 @@ export function fetchSql( return { records: [] as DataTableRecord[], textBasedQueryColumns: [], + textBasedHeaderWarning: undefined, }; }) .catch((err) => { diff --git a/src/plugins/discover/public/application/main/utils/get_data_view_by_text_based_query_lang.test.ts b/src/plugins/discover/public/application/main/utils/get_data_view_by_text_based_query_lang.test.ts index 0b81061ab68ff..0dfbd84224f4d 100644 --- a/src/plugins/discover/public/application/main/utils/get_data_view_by_text_based_query_lang.test.ts +++ b/src/plugins/discover/public/application/main/utils/get_data_view_by_text_based_query_lang.test.ts @@ -20,13 +20,13 @@ describe('getDataViewByTextBasedQueryLang', () => { }); const services = discoverServiceMock; it('returns the current dataview if is adhoc and query has not changed', async () => { - const query = { sql: 'Select * from data-view-ad-hoc-title' }; + const query = { esql: 'from data-view-ad-hoc-title' }; const dataView = await getDataViewByTextBasedQueryLang(query, dataViewAdHoc, services); expect(dataView).toStrictEqual(dataViewAdHoc); }); it('creates an adhoc dataview if the current dataview is persistent and query has not changed', async () => { - const query = { sql: 'Select * from the-data-view-title' }; + const query = { esql: 'from the-data-view-title' }; const dataView = await getDataViewByTextBasedQueryLang(query, dataViewMock, services); expect(dataView.isPersisted()).toEqual(false); expect(dataView.timeFieldName).toBe('@timestamp'); @@ -40,7 +40,7 @@ describe('getDataViewByTextBasedQueryLang', () => { title: 'test-1', timeFieldName: undefined, }); - const query = { sql: 'Select * from the-data-view-title' }; + const query = { esql: 'from the-data-view-title' }; const dataView = await getDataViewByTextBasedQueryLang(query, dataViewAdHoc, services); expect(dataView.isPersisted()).toEqual(false); expect(dataView.timeFieldName).toBeUndefined(); diff --git a/src/plugins/discover/public/application/main/utils/get_data_view_by_text_based_query_lang.ts b/src/plugins/discover/public/application/main/utils/get_data_view_by_text_based_query_lang.ts index 3b38b95dfceb1..09ac5f1e87686 100644 --- a/src/plugins/discover/public/application/main/utils/get_data_view_by_text_based_query_lang.ts +++ b/src/plugins/discover/public/application/main/utils/get_data_view_by_text_based_query_lang.ts @@ -5,7 +5,11 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { AggregateQuery, getIndexPatternFromSQLQuery } from '@kbn/es-query'; +import { + AggregateQuery, + getIndexPatternFromSQLQuery, + getIndexPatternFromESQLQuery, +} from '@kbn/es-query'; import { DataView } from '@kbn/data-views-plugin/common'; import { DiscoverServices } from '../../../build_services'; @@ -14,9 +18,16 @@ export async function getDataViewByTextBasedQueryLang( currentDataView: DataView | undefined, services: DiscoverServices ) { - const text = 'sql' in query ? query.sql : undefined; + let indexPatternFromQuery = ''; + if ('sql' in query) { + indexPatternFromQuery = getIndexPatternFromSQLQuery(query.sql); + } + if ('esql' in query) { + indexPatternFromQuery = getIndexPatternFromESQLQuery(query.esql); + } + // we should find a better way to work with ESQL queries which dont need a dataview + if (!indexPatternFromQuery && currentDataView) return currentDataView; - const indexPatternFromQuery = getIndexPatternFromSQLQuery(text); if ( currentDataView?.isPersisted() || indexPatternFromQuery !== currentDataView?.getIndexPattern() diff --git a/src/plugins/discover/public/application/main/utils/get_raw_record_type.test.ts b/src/plugins/discover/public/application/main/utils/get_raw_record_type.test.ts index 146a5a80a125f..781cfef1387a9 100644 --- a/src/plugins/discover/public/application/main/utils/get_raw_record_type.test.ts +++ b/src/plugins/discover/public/application/main/utils/get_raw_record_type.test.ts @@ -15,8 +15,8 @@ describe('getRawRecordType', () => { expect(mode).toEqual(RecordRawType.DOCUMENT); }); - it('returns sql for Query type query', () => { - const mode = getRawRecordType({ sql: 'SELECT * from foo' }); + it('returns esql for Query type query', () => { + const mode = getRawRecordType({ esql: 'from foo' }); expect(mode).toEqual(RecordRawType.PLAIN); }); diff --git a/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts b/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts index 103520c71998b..19e9f6a64c88b 100644 --- a/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts +++ b/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts @@ -10,7 +10,7 @@ import { getStateDefaults } from './get_state_defaults'; import { createSearchSourceMock } from '@kbn/data-plugin/public/mocks'; import { VIEW_MODE } from '@kbn/saved-search-plugin/common'; import { dataViewWithTimefieldMock } from '../../../__mocks__/data_view_with_timefield'; -import { savedSearchMock, savedSearchMockWithSQL } from '../../../__mocks__/saved_search'; +import { savedSearchMock, savedSearchMockWithESQL } from '../../../__mocks__/saved_search'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; import { discoverServiceMock } from '../../../__mocks__/services'; @@ -81,7 +81,7 @@ describe('getStateDefaults', () => { const actualForUndefinedViewMode = getStateDefaults({ services: discoverServiceMock, savedSearch: { - ...savedSearchMockWithSQL, + ...savedSearchMockWithESQL, viewMode: undefined, }, }); @@ -90,7 +90,7 @@ describe('getStateDefaults', () => { const actualForTextBasedWithInvalidViewMode = getStateDefaults({ services: discoverServiceMock, savedSearch: { - ...savedSearchMockWithSQL, + ...savedSearchMockWithESQL, viewMode: VIEW_MODE.AGGREGATED_LEVEL, }, }); @@ -99,7 +99,7 @@ describe('getStateDefaults', () => { const actualForTextBasedWithValidViewMode = getStateDefaults({ services: discoverServiceMock, savedSearch: { - ...savedSearchMockWithSQL, + ...savedSearchMockWithESQL, viewMode: VIEW_MODE.DOCUMENT_LEVEL, }, }); diff --git a/src/plugins/discover/public/application/main/utils/is_text_based_query.test.ts b/src/plugins/discover/public/application/main/utils/is_text_based_query.test.ts index 53e85216ba0bf..78f7b24d3c10a 100644 --- a/src/plugins/discover/public/application/main/utils/is_text_based_query.test.ts +++ b/src/plugins/discover/public/application/main/utils/is_text_based_query.test.ts @@ -12,6 +12,7 @@ describe('isTextBasedQuery', () => { it('should work correctly', () => { expect(isTextBasedQuery({ query: '', language: 'lucene' })).toEqual(false); expect(isTextBasedQuery({ sql: 'SELECT * from foo' })).toEqual(true); + expect(isTextBasedQuery({ esql: 'from foo' })).toEqual(true); expect(isTextBasedQuery()).toEqual(false); }); }); diff --git a/src/plugins/discover/public/application/types.ts b/src/plugins/discover/public/application/types.ts index 57677236cbf7a..3fc375a5ebcb7 100644 --- a/src/plugins/discover/public/application/types.ts +++ b/src/plugins/discover/public/application/types.ts @@ -6,6 +6,10 @@ * Side Public License, v 1. */ +import type { DatatableColumn } from '@kbn/expressions-plugin/common'; +import type { DataTableRecord } from '@kbn/discover-utils/types'; +import type { SearchResponseInterceptedWarning } from '@kbn/search-response-warnings'; + export enum FetchStatus { UNINITIALIZED = 'uninitialized', LOADING = 'loading', @@ -16,3 +20,10 @@ export enum FetchStatus { } export type DiscoverDisplayMode = 'embedded' | 'standalone'; + +export interface RecordsFetchResponse { + records: DataTableRecord[]; + textBasedQueryColumns?: DatatableColumn[]; + textBasedHeaderWarning?: string; + interceptedWarnings?: SearchResponseInterceptedWarning[]; +} diff --git a/src/plugins/discover/public/build_services.ts b/src/plugins/discover/public/build_services.ts index 254292e6d07e6..b903d2485bdc4 100644 --- a/src/plugins/discover/public/build_services.ts +++ b/src/plugins/discover/public/build_services.ts @@ -7,7 +7,6 @@ */ import { History } from 'history'; -import { memoize } from 'lodash'; import { Capabilities, @@ -52,7 +51,9 @@ import type { LensPublicStart } from '@kbn/lens-plugin/public'; import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import type { SettingsStart } from '@kbn/core-ui-settings-browser'; import type { ContentClient } from '@kbn/content-management-plugin/public'; +import { memoize } from 'lodash'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import { getHistory } from './kibana_services'; import { DiscoverStartPlugins } from './plugin'; import { DiscoverContextAppLocator } from './application/context/services/locator'; @@ -111,6 +112,7 @@ export interface DiscoverServices { uiActions: UiActionsStart; contentClient: ContentClient; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } export const buildServices = memoize(function ( @@ -171,5 +173,6 @@ export const buildServices = memoize(function ( uiActions: plugins.uiActions, contentClient: plugins.contentManagement.client, serverless: plugins.serverless, + noDataPage: plugins.noDataPage, }; }); diff --git a/src/plugins/discover/public/components/common/deferred_spinner.tsx b/src/plugins/discover/public/components/common/deferred_spinner.tsx deleted file mode 100644 index 11f77281f9eb0..0000000000000 --- a/src/plugins/discover/public/components/common/deferred_spinner.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useEffect, useRef, useState } from 'react'; - -/** - * A component that shows it children with a 300ms delay. This is good for wrapping - * loading spinners for tasks that might potentially be very fast (e.g. loading async chunks). - * That way we don't show a quick flash of the spinner before the actual content and will only - * show the spinner once loading takes a bit longer (more than 300ms). - */ -export const DeferredSpinner: React.FC = ({ children }) => { - const timeoutRef = useRef(); - const [showContent, setShowContent] = useState(false); - useEffect(() => { - timeoutRef.current = window.setTimeout(() => { - setShowContent(true); - }, 300); - return () => { - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - } - }; - }, []); - - return showContent ? {children} : null; -}; diff --git a/src/plugins/discover/public/components/discover_container/discover_container.test.tsx b/src/plugins/discover/public/components/discover_container/discover_container.test.tsx index 9b963f69ccf84..708fc93e63b81 100644 --- a/src/plugins/discover/public/components/discover_container/discover_container.test.tsx +++ b/src/plugins/discover/public/components/discover_container/discover_container.test.tsx @@ -39,7 +39,7 @@ const TestComponent = (props: Partial) => { return ( )} getDiscoverServices={getDiscoverServicesMock} diff --git a/src/plugins/discover/public/components/discover_container/discover_container.tsx b/src/plugins/discover/public/components/discover_container/discover_container.tsx index 6cd70ff430255..28a596946bd18 100644 --- a/src/plugins/discover/public/components/discover_container/discover_container.tsx +++ b/src/plugins/discover/public/components/discover_container/discover_container.tsx @@ -27,8 +27,9 @@ export interface DiscoverContainerInternalProps { overrideServices: Partial; getDiscoverServices: () => Promise; scopedHistory: ScopedHistory; - customize: CustomizationCallback; + customizationCallbacks: CustomizationCallback[]; isDev: boolean; + isLoading?: boolean; } const discoverContainerWrapperCss = css` @@ -45,12 +46,12 @@ const discoverContainerWrapperCss = css` export const DiscoverContainerInternal = ({ overrideServices, scopedHistory, - customize, + customizationCallbacks, isDev, getDiscoverServices, + isLoading = false, }: DiscoverContainerInternalProps) => { const [discoverServices, setDiscoverServices] = useState(); - const customizationCallbacks = useMemo(() => [customize], [customize]); const [initialized, setInitialized] = useState(false); useEffect(() => { @@ -68,7 +69,7 @@ export const DiscoverContainerInternal = ({ return { ...discoverServices, ...overrideServices }; }, [discoverServices, overrideServices]); - if (!initialized || !services) { + if (!initialized || !services || isLoading) { return ( diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_cell_actions.test.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_cell_actions.test.tsx deleted file mode 100644 index 079a26c265d27..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_cell_actions.test.tsx +++ /dev/null @@ -1,159 +0,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. - */ -const mockCopyToClipboard = jest.fn((value) => true); -jest.mock('@elastic/eui', () => { - const original = jest.requireActual('@elastic/eui'); - return { - ...original, - copyToClipboard: (value: string) => mockCopyToClipboard(value), - }; -}); - -jest.mock('../../hooks/use_discover_services', () => { - const services = { - toastNotifications: { - addInfo: jest.fn(), - }, - }; - const originalModule = jest.requireActual('../../hooks/use_discover_services'); - return { - ...originalModule, - useDiscoverServices: () => services, - }; -}); - -import React from 'react'; -import { mountWithIntl } from '@kbn/test-jest-helpers'; -import { findTestSubject } from '@elastic/eui/lib/test'; -import { FilterInBtn, FilterOutBtn, buildCellActions, CopyBtn } from './discover_grid_cell_actions'; -import { DiscoverGridContext } from './discover_grid_context'; -import { EuiButton } from '@elastic/eui'; -import { discoverGridContextMock } from '../../__mocks__/grid_context'; -import { DataViewField } from '@kbn/data-views-plugin/public'; - -describe('Discover cell actions ', function () { - it('should not show cell actions for unfilterable fields', async () => { - expect(buildCellActions({ name: 'foo', filterable: false } as DataViewField)).toEqual([ - CopyBtn, - ]); - }); - - it('should show filter actions for filterable fields', async () => { - expect(buildCellActions({ name: 'foo', filterable: true } as DataViewField, jest.fn())).toEqual( - [FilterInBtn, FilterOutBtn, CopyBtn] - ); - }); - - it('should show Copy action for _source field', async () => { - expect( - buildCellActions({ name: '_source', type: '_source', filterable: false } as DataViewField) - ).toEqual([CopyBtn]); - }); - - it('triggers filter function when FilterInBtn is clicked', async () => { - const component = mountWithIntl( - - } - rowIndex={1} - colIndex={1} - columnId="extension" - isExpanded={false} - /> - - ); - const button = findTestSubject(component, 'filterForButton'); - await button.simulate('click'); - expect(discoverGridContextMock.onFilter).toHaveBeenCalledWith( - discoverGridContextMock.dataView.fields.getByName('extension'), - 'jpg', - '+' - ); - }); - it('triggers filter function when FilterInBtn is clicked for a non-provided value', async () => { - const component = mountWithIntl( - - } - rowIndex={0} - colIndex={1} - columnId="extension" - isExpanded={false} - /> - - ); - const button = findTestSubject(component, 'filterForButton'); - await button.simulate('click'); - expect(discoverGridContextMock.onFilter).toHaveBeenCalledWith( - discoverGridContextMock.dataView.fields.getByName('extension'), - undefined, - '+' - ); - }); - it('triggers filter function when FilterInBtn is clicked for an empty string value', async () => { - const component = mountWithIntl( - - } - rowIndex={4} - colIndex={1} - columnId="message" - isExpanded={false} - /> - - ); - const button = findTestSubject(component, 'filterForButton'); - await button.simulate('click'); - expect(discoverGridContextMock.onFilter).toHaveBeenCalledWith( - discoverGridContextMock.dataView.fields.getByName('message'), - '', - '+' - ); - }); - it('triggers filter function when FilterOutBtn is clicked', async () => { - const component = mountWithIntl( - - } - rowIndex={1} - colIndex={1} - columnId="extension" - isExpanded={false} - /> - - ); - const button = findTestSubject(component, 'filterOutButton'); - await button.simulate('click'); - expect(discoverGridContextMock.onFilter).toHaveBeenCalledWith( - discoverGridContextMock.dataView.fields.getByName('extension'), - 'jpg', - '-' - ); - }); - it('triggers clipboard copy when CopyBtn is clicked', async () => { - const component = mountWithIntl( - - } - rowIndex={1} - colIndex={1} - columnId="extension" - isExpanded={false} - /> - - ); - const button = findTestSubject(component, 'copyClipboardButton'); - await button.simulate('click'); - expect(mockCopyToClipboard).toHaveBeenCalledWith('jpg'); - }); -}); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_flyout.test.tsx b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx similarity index 96% rename from src/plugins/discover/public/components/discover_grid/discover_grid_flyout.test.tsx rename to src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx index e42fae3eacd3b..9593c6c81c31e 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_flyout.test.tsx +++ b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx @@ -14,8 +14,6 @@ import { DiscoverGridFlyout, DiscoverGridFlyoutProps } from './discover_grid_fly import { createFilterManagerMock } from '@kbn/data-plugin/public/query/filter_manager/filter_manager.mock'; import { dataViewMock, esHitsMock } from '@kbn/discover-utils/src/__mocks__'; import { DiscoverServices } from '../../build_services'; -import { DocViewsRegistry } from '../../services/doc_views/doc_views_registry'; -import { setDocViewsRegistry } from '../../kibana_services'; import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; @@ -23,6 +21,8 @@ import type { DataTableRecord, EsHitRecord } from '@kbn/discover-utils/types'; import { buildDataTableRecord } from '@kbn/discover-utils'; import { act } from 'react-dom/test-utils'; import { ReactWrapper } from 'enzyme'; +import { setUnifiedDocViewerServices } from '@kbn/unified-doc-viewer-plugin/public/plugin'; +import { mockUnifiedDocViewerServices } from '@kbn/unified-doc-viewer-plugin/public/__mocks__'; const waitNextTick = () => new Promise((resolve) => setTimeout(resolve, 0)); @@ -34,8 +34,6 @@ const waitNextUpdate = async (component: ReactWrapper) => { }; describe('Discover flyout', function () { - setDocViewsRegistry(new DocViewsRegistry()); - const mountComponent = async ({ dataView, hits, @@ -60,6 +58,7 @@ describe('Discover flyout', function () { contextLocator: { getRedirectUrl: jest.fn(() => 'mock-context-redirect-url') }, singleDocLocator: { getRedirectUrl: jest.fn(() => 'mock-doc-redirect-url') }, } as unknown as DiscoverServices; + setUnifiedDocViewerServices(mockUnifiedDocViewerServices); const hit = buildDataTableRecord( hitIndex ? esHitsMock[hitIndex] : (esHitsMock[0] as EsHitRecord), @@ -200,7 +199,7 @@ describe('Discover flyout', function () { it('should not render single/surrounding views for text based', async () => { const { component } = await mountComponent({ - query: { sql: 'Select * from indexpattern' }, + query: { esql: 'FROM indexpattern' }, }); const singleDocumentView = findTestSubject(component, 'docTableRowAction'); expect(singleDocumentView.length).toBeFalsy(); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_flyout.tsx b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx similarity index 95% rename from src/plugins/discover/public/components/discover_grid/discover_grid_flyout.tsx rename to src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx index f277ad47200ff..a9130df52738e 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_flyout.tsx +++ b/src/plugins/discover/public/components/discover_grid_flyout/discover_grid_flyout.tsx @@ -27,8 +27,8 @@ import { } from '@elastic/eui'; import type { Filter, Query, AggregateQuery } from '@kbn/es-query'; import type { DataTableRecord } from '@kbn/discover-utils/types'; -import { DocViewer } from '../../services/doc_views/components/doc_viewer/doc_viewer'; -import { DocViewFilterFn } from '../../services/doc_views/doc_views_types'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import { UnifiedDocViewer } from '@kbn/unified-doc-viewer-plugin/public'; import { useNavigationProps } from '../../hooks/use_navigation_props'; import { useDiscoverServices } from '../../hooks/use_discover_services'; import { isTextBasedQuery } from '../../application/main/utils/is_text_based_query'; @@ -45,7 +45,7 @@ export interface DiscoverGridFlyoutProps { onClose: () => void; onFilter?: DocViewFilterFn; onRemoveColumn: (column: string) => void; - setExpandedDoc: (doc: DataTableRecord) => void; + setExpandedDoc: (doc?: DataTableRecord) => void; } function getIndexByDocId(hits: DataTableRecord[], id: string) { @@ -120,7 +120,7 @@ export function DiscoverGridFlyout({

    @@ -216,7 +216,7 @@ export function DiscoverGridFlyout({ pageCount={pageCount} activePage={activePage} onPageClick={setPage} - className="dscTable__flyoutDocumentNavigation" + className="unifiedDataTable__flyoutDocumentNavigation" compressed data-test-subj="dscDocNavigation" /> @@ -225,7 +225,7 @@ export function DiscoverGridFlyout({ - ); } + +// eslint-disable-next-line import/no-default-export +export default DiscoverGridFlyout; diff --git a/src/plugins/discover/public/components/discover_grid_flyout/index.ts b/src/plugins/discover/public/components/discover_grid_flyout/index.ts new file mode 100644 index 0000000000000..da7fa274494b1 --- /dev/null +++ b/src/plugins/discover/public/components/discover_grid_flyout/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { withSuspense } from '@kbn/shared-ux-utility'; +import { lazy } from 'react'; +export type { DiscoverGridFlyoutProps } from './discover_grid_flyout'; + +export const DiscoverGridFlyout = withSuspense(lazy(() => import('./discover_grid_flyout'))); diff --git a/src/plugins/discover/public/components/doc_table/components/pager/tool_bar_pagination.tsx b/src/plugins/discover/public/components/doc_table/components/pager/tool_bar_pagination.tsx index 18ba8817391ac..bd0e2e3439451 100644 --- a/src/plugins/discover/public/components/doc_table/components/pager/tool_bar_pagination.tsx +++ b/src/plugins/discover/public/components/doc_table/components/pager/tool_bar_pagination.tsx @@ -19,7 +19,7 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { euiLightVars } from '@kbn/ui-theme'; -import { getRowsPerPageOptions } from '../../../../utils/rows_per_page'; +import { getRowsPerPageOptions } from '@kbn/unified-data-table'; export const MAX_ROWS_PER_PAGE_OPTION = 100; diff --git a/src/plugins/discover/public/components/doc_table/components/table_row.test.tsx b/src/plugins/discover/public/components/doc_table/components/table_row.test.tsx index d9fbe1e8071ce..44775021eda9e 100644 --- a/src/plugins/discover/public/components/doc_table/components/table_row.test.tsx +++ b/src/plugins/discover/public/components/doc_table/components/table_row.test.tsx @@ -9,13 +9,10 @@ import React from 'react'; import { mountWithIntl, findTestSubject } from '@kbn/test-jest-helpers'; import { TableRow, TableRowProps } from './table_row'; -import { setDocViewsRegistry } from '../../../kibana_services'; import { createFilterManagerMock } from '@kbn/data-plugin/public/query/filter_manager/filter_manager.mock'; import { dataViewWithTimefieldMock } from '../../../__mocks__/data_view_with_timefield'; -import { DocViewsRegistry } from '../../../services/doc_views/doc_views_registry'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { discoverServiceMock } from '../../../__mocks__/services'; -import { DocViewer } from '../../../services/doc_views/components/doc_viewer'; import { DOC_HIDE_TIME_COLUMN_SETTING, MAX_DOC_FIELDS_DISPLAYED } from '@kbn/discover-utils'; import { buildDataTableRecord } from '@kbn/discover-utils'; @@ -81,13 +78,8 @@ describe('Doc table row component', () => { useNewFieldsApi: true, filterManager: mockFilterManager, addBasePath: (path: string) => path, - DocViewer, } as unknown as TableRowProps; - beforeEach(() => { - setDocViewsRegistry(new DocViewsRegistry()); - }); - it('should render __document__ column', () => { const component = mountComponent({ ...defaultProps, columns: [] }); const docTableField = findTestSubject(component, 'docTableField'); diff --git a/src/plugins/discover/public/components/doc_table/components/table_row.tsx b/src/plugins/discover/public/components/doc_table/components/table_row.tsx index e1c00ec3397c0..6057cd64aa473 100644 --- a/src/plugins/discover/public/components/doc_table/components/table_row.tsx +++ b/src/plugins/discover/public/components/doc_table/components/table_row.tsx @@ -19,10 +19,10 @@ import type { } from '@kbn/discover-utils/types'; import { formatFieldValue } from '@kbn/discover-utils'; import { DOC_HIDE_TIME_COLUMN_SETTING, MAX_DOC_FIELDS_DISPLAYED } from '@kbn/discover-utils'; -import { DocViewRenderProps } from '../../../services/doc_views/doc_views_types'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import { UnifiedDocViewer } from '@kbn/unified-doc-viewer-plugin/public'; import { TableCell } from './table_row/table_cell'; import { formatRow, formatTopLevelObject } from '../utils/row_formatter'; -import { DocViewFilterFn } from '../../../services/doc_views/doc_views_types'; import { TableRowDetails } from './table_row_details'; import { useDiscoverServices } from '../../../hooks/use_discover_services'; @@ -43,7 +43,6 @@ export interface TableRowProps { shouldShowFieldHandler: ShouldShowFieldInTableHandler; onAddColumn?: (column: string) => void; onRemoveColumn?: (column: string) => void; - DocViewer: React.ComponentType; } export const TableRow = ({ @@ -59,7 +58,6 @@ export const TableRow = ({ shouldShowFieldHandler, onAddColumn, onRemoveColumn, - DocViewer, }: TableRowProps) => { const { uiSettings, fieldFormats } = useDiscoverServices(); const [maxEntries, hideTimeColumn] = useMemo( @@ -223,7 +221,7 @@ export const TableRow = ({ savedSearchId={savedSearchId} isPlainRecord={isPlainRecord} > - ); diff --git a/src/plugins/discover/public/components/doc_table/doc_table_wrapper.test.tsx b/src/plugins/discover/public/components/doc_table/doc_table_wrapper.test.tsx index 2f05c0c2b357d..17925373186f3 100644 --- a/src/plugins/discover/public/components/doc_table/doc_table_wrapper.test.tsx +++ b/src/plugins/discover/public/components/doc_table/doc_table_wrapper.test.tsx @@ -15,7 +15,6 @@ import { discoverServiceMock } from '../../__mocks__/services'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { buildDataTableRecord } from '@kbn/discover-utils'; import type { EsHitRecord } from '@kbn/discover-utils/types'; -import { DocViewer } from '../../services/doc_views/components/doc_viewer'; describe('Doc table component', () => { const mountComponent = (customProps?: Partial) => { @@ -48,7 +47,6 @@ describe('Doc table component', () => { render: () => { return
    mock
    ; }, - DocViewer, ...(customProps || {}), }; diff --git a/src/plugins/discover/public/components/doc_table/doc_table_wrapper.tsx b/src/plugins/discover/public/components/doc_table/doc_table_wrapper.tsx index 8e32b97956cea..a61523b6647c3 100644 --- a/src/plugins/discover/public/components/doc_table/doc_table_wrapper.tsx +++ b/src/plugins/discover/public/components/doc_table/doc_table_wrapper.tsx @@ -14,9 +14,9 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { Filter } from '@kbn/es-query'; import type { DataTableRecord } from '@kbn/discover-utils/types'; import { SHOW_MULTIFIELDS, getShouldShowFieldHandler } from '@kbn/discover-utils'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import { TableHeader } from './components/table_header/table_header'; import { TableRow } from './components/table_row'; -import { DocViewFilterFn, DocViewRenderProps } from '../../services/doc_views/doc_views_types'; import { useDiscoverServices } from '../../hooks/use_discover_services'; export interface DocTableProps { @@ -89,10 +89,6 @@ export interface DocTableProps { * Remove column callback */ onRemoveColumn?: (column: string) => void; - /** - * Doc viewer component - */ - DocViewer: React.ComponentType; } export interface DocTableRenderProps { @@ -133,7 +129,6 @@ export const DocTableWrapper = forwardRef( sharedItemTitle, dataTestSubj, isLoading, - DocViewer, }: DocTableWrapperProps, ref ) => { @@ -191,7 +186,6 @@ export const DocTableWrapper = forwardRef( shouldShowFieldHandler={shouldShowFieldHandler} onAddColumn={onAddColumn} onRemoveColumn={onRemoveColumn} - DocViewer={DocViewer} isPlainRecord={isPlainRecord} rows={rows} /> @@ -207,7 +201,6 @@ export const DocTableWrapper = forwardRef( shouldShowFieldHandler, onAddColumn, onRemoveColumn, - DocViewer, isPlainRecord, rows, ] diff --git a/src/plugins/discover/public/customizations/customization_service.ts b/src/plugins/discover/public/customizations/customization_service.ts index 4a9b9bf2588af..0b57ba37e07dc 100644 --- a/src/plugins/discover/public/customizations/customization_service.ts +++ b/src/plugins/discover/public/customizations/customization_service.ts @@ -7,9 +7,16 @@ */ import { filter, map, Observable, startWith, Subject } from 'rxjs'; -import type { SearchBarCustomization, TopNavCustomization } from './customization_types'; +import type { + SearchBarCustomization, + TopNavCustomization, + UnifiedHistogramCustomization, +} from './customization_types'; -export type DiscoverCustomization = SearchBarCustomization | TopNavCustomization; +export type DiscoverCustomization = + | SearchBarCustomization + | TopNavCustomization + | UnifiedHistogramCustomization; export type DiscoverCustomizationId = DiscoverCustomization['id']; diff --git a/src/plugins/discover/public/customizations/customization_types/histogram_customization.tsx b/src/plugins/discover/public/customizations/customization_types/histogram_customization.tsx new file mode 100644 index 0000000000000..73313b2f37ba9 --- /dev/null +++ b/src/plugins/discover/public/customizations/customization_types/histogram_customization.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { UnifiedHistogramContainerProps } from '@kbn/unified-histogram-plugin/public'; + +interface UnifiedHistogramCustomizationId { + id: 'unified_histogram'; +} + +export type UnifiedHistogramCustomization = UnifiedHistogramCustomizationId & + Pick< + UnifiedHistogramContainerProps, + 'onFilter' | 'onBrushEnd' | 'withDefaultActions' | 'disabledActions' + >; diff --git a/src/plugins/discover/public/customizations/customization_types/index.ts b/src/plugins/discover/public/customizations/customization_types/index.ts index e7ea9591f8ad4..e920a68574b93 100644 --- a/src/plugins/discover/public/customizations/customization_types/index.ts +++ b/src/plugins/discover/public/customizations/customization_types/index.ts @@ -8,3 +8,4 @@ export * from './search_bar_customization'; export * from './top_nav_customization'; +export * from './histogram_customization'; diff --git a/src/plugins/discover/public/customizations/index.ts b/src/plugins/discover/public/customizations/index.ts index bc0a7e03525c9..0c9a94ac8adad 100644 --- a/src/plugins/discover/public/customizations/index.ts +++ b/src/plugins/discover/public/customizations/index.ts @@ -9,3 +9,4 @@ export * from './customization_types'; export * from './customization_provider'; export * from './types'; +export type { DiscoverCustomization, DiscoverCustomizationService } from './customization_service'; diff --git a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx index e6caae3c4a7dd..9a44ae3834f7c 100644 --- a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx +++ b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx @@ -59,30 +59,34 @@ import { SORT_DEFAULT_ORDER_SETTING, buildDataTableRecord, } from '@kbn/discover-utils'; -import { VIEW_MODE, DISABLE_SHARD_FAILURE_WARNING } from '../../common/constants'; +import type { UnifiedDataTableProps } from '@kbn/unified-data-table'; +import type { UnifiedDataTableSettings } from '@kbn/unified-data-table'; +import { columnActions } from '@kbn/unified-data-table'; +import { + VIEW_MODE, + DISABLE_SHARD_FAILURE_WARNING, + getDefaultRowsPerPage, +} from '../../common/constants'; import type { ISearchEmbeddable, SearchInput, SearchOutput } from './types'; import type { DiscoverServices } from '../build_services'; import { getSortForEmbeddable, SortPair } from '../utils/sorting'; import { SEARCH_EMBEDDABLE_TYPE, SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER_ID } from './constants'; import { SavedSearchEmbeddableComponent } from './saved_search_embeddable_component'; -import * as columnActions from '../components/doc_table/actions/columns'; import { handleSourceColumnState } from '../utils/state_helpers'; -import type { DiscoverGridProps } from '../components/discover_grid/discover_grid'; -import type { DiscoverGridSettings } from '../components/discover_grid/types'; import type { DocTableProps } from '../components/doc_table/doc_table_wrapper'; import { updateSearchSource } from './utils/update_search_source'; import { FieldStatisticsTable } from '../application/main/components/field_stats_table'; +import { fetchTextBased } from '../application/main/utils/fetch_text_based'; import { isTextBasedQuery } from '../application/main/utils/is_text_based_query'; import { getValidViewMode } from '../application/main/utils/get_valid_view_mode'; -import { fetchSql } from '../application/main/utils/fetch_sql'; import { ADHOC_DATA_VIEW_RENDER_EVENT } from '../constants'; import { getDiscoverLocatorParams } from './get_discover_locator_params'; -export type SearchProps = Partial & +export type SearchProps = Partial & Partial & { savedSearchId?: string; filters?: Filter[]; - settings?: DiscoverGridSettings; + settings?: UnifiedDataTableSettings; description?: string; sharedItemTitle?: string; inspectorAdapters?: Adapters; @@ -321,12 +325,12 @@ export class SavedSearchEmbeddable const query = savedSearch.searchSource.getField('query'); const dataView = savedSearch.searchSource.getField('index')!; - const useSql = this.isTextBasedSearch(savedSearch); + const useTextBased = this.isTextBasedSearch(savedSearch); try { - // Request SQL data - if (useSql && query) { - const result = await fetchSql( + // Request text based data + if (useTextBased && query) { + const result = await fetchTextBased( savedSearch.searchSource.getField('query')!, dataView, this.services.data, @@ -585,7 +589,10 @@ export class SavedSearchEmbeddable searchProps.sharedItemTitle = this.panelTitle; searchProps.searchTitle = this.panelTitle; searchProps.rowHeightState = this.input.rowHeight || savedSearch.rowHeight; - searchProps.rowsPerPageState = this.input.rowsPerPage || savedSearch.rowsPerPage; + searchProps.rowsPerPageState = + this.input.rowsPerPage || + savedSearch.rowsPerPage || + getDefaultRowsPerPage(this.services.uiSettings); searchProps.filters = savedSearch.searchSource.getField('filter') as Filter[]; searchProps.savedSearchId = savedSearch.id; diff --git a/src/plugins/discover/public/embeddable/saved_search_embeddable_component.tsx b/src/plugins/discover/public/embeddable/saved_search_embeddable_component.tsx index fd28f3114211f..f8c7aa39c1a7c 100644 --- a/src/plugins/discover/public/embeddable/saved_search_embeddable_component.tsx +++ b/src/plugins/discover/public/embeddable/saved_search_embeddable_component.tsx @@ -8,11 +8,8 @@ import React from 'react'; import { AggregateQuery, Query } from '@kbn/es-query'; -import { - DiscoverGridEmbeddable, - DiscoverGridEmbeddableProps, - DataLoadingState, -} from './saved_search_grid'; +import { DataLoadingState } from '@kbn/unified-data-table'; +import { DiscoverGridEmbeddable, DiscoverGridEmbeddableProps } from './saved_search_grid'; import { DiscoverDocTableEmbeddable } from '../components/doc_table/create_doc_table_embeddable'; import { DocTableEmbeddableProps } from '../components/doc_table/doc_table_embeddable'; import { isTextBasedQuery } from '../application/main/utils/is_text_based_query'; @@ -47,7 +44,7 @@ export function SavedSearchEmbeddableComponent({ loadingState={searchProps.isLoading ? DataLoadingState.loading : DataLoadingState.loaded} showFullScreenButton={false} query={query} - className="dscDiscoverGrid" + className="unifiedDataTable" /> ); } diff --git a/src/plugins/discover/public/embeddable/saved_search_grid.tsx b/src/plugins/discover/public/embeddable/saved_search_grid.tsx index b818286660301..580a55534b573 100644 --- a/src/plugins/discover/public/embeddable/saved_search_grid.tsx +++ b/src/plugins/discover/public/embeddable/saved_search_grid.tsx @@ -5,43 +5,80 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import React, { memo, useState } from 'react'; +import React, { memo, useCallback, useState } from 'react'; import type { DataTableRecord } from '@kbn/discover-utils/types'; +import { AggregateQuery, Query } from '@kbn/es-query'; import type { SearchResponseInterceptedWarning } from '@kbn/search-response-warnings'; import { - DiscoverGrid, - DiscoverGridProps, - DataLoadingState as DiscoverDataLoadingState, -} from '../components/discover_grid/discover_grid'; + DataLoadingState as DiscoverGridLoadingState, + UnifiedDataTable, +} from '@kbn/unified-data-table'; +import type { UnifiedDataTableProps } from '@kbn/unified-data-table'; import './saved_search_grid.scss'; -import { DiscoverGridFlyout } from '../components/discover_grid/discover_grid_flyout'; +import { MAX_DOC_FIELDS_DISPLAYED, ROW_HEIGHT_OPTION, SHOW_MULTIFIELDS } from '@kbn/discover-utils'; +import { DiscoverGridFlyout } from '../components/discover_grid_flyout'; import { SavedSearchEmbeddableBase } from './saved_search_embeddable_base'; -export { DataLoadingState } from '../components/discover_grid/discover_grid'; +import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../components/discover_tour'; -export interface DiscoverGridEmbeddableProps extends DiscoverGridProps { +export interface DiscoverGridEmbeddableProps extends UnifiedDataTableProps { totalHitCount?: number; + query?: AggregateQuery | Query; interceptedWarnings?: SearchResponseInterceptedWarning[]; + onAddColumn: (column: string) => void; + onRemoveColumn: (column: string) => void; + savedSearchId?: string; } -export const DiscoverGridMemoized = memo(DiscoverGrid); +export const DataGridMemoized = memo(UnifiedDataTable); export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) { const { interceptedWarnings, ...gridProps } = props; const [expandedDoc, setExpandedDoc] = useState(undefined); + const renderDocumentView = useCallback( + (hit: DataTableRecord, displayedRows: DataTableRecord[], displayedColumns: string[]) => ( + setExpandedDoc(undefined)} + setExpandedDoc={setExpandedDoc} + query={props.query} + /> + ), + [ + props.dataView, + props.onAddColumn, + props.onFilter, + props.onRemoveColumn, + props.query, + props.savedSearchId, + ] + ); + return ( - ); diff --git a/src/plugins/discover/public/hooks/use_row_heights_options.test.tsx b/src/plugins/discover/public/hooks/use_row_heights_options.test.tsx deleted file mode 100644 index 113f34ab723dd..0000000000000 --- a/src/plugins/discover/public/hooks/use_row_heights_options.test.tsx +++ /dev/null @@ -1,107 +0,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, { ReactNode } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; -import { Storage } from '@kbn/kibana-utils-plugin/public'; -import { DiscoverServices } from '../build_services'; -import { LocalStorageMock } from '../__mocks__/local_storage_mock'; -import { uiSettingsMock } from '../__mocks__/ui_settings'; -import { useRowHeightsOptions } from './use_row_heights_options'; -import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; - -const CONFIG_ROW_HEIGHT = 3; - -const getWrapper = (services: DiscoverServices) => { - return ({ children }: { children: ReactNode }) => ( - {children} - ); -}; - -describe('useRowHeightsOptions', () => { - test('should apply rowHeight from savedSearch', () => { - const { result } = renderHook( - () => { - return useRowHeightsOptions({ - rowHeightState: 2, - }); - }, - { - wrapper: getWrapper({ - uiSettings: uiSettingsMock, - storage: new LocalStorageMock({}) as unknown as Storage, - } as DiscoverServices), - } - ); - - expect(result.current.defaultHeight).toEqual({ lineCount: 2 }); - }); - - test('should apply rowHeight from local storage', () => { - const { result } = renderHook( - () => { - return useRowHeightsOptions({}); - }, - { - wrapper: getWrapper({ - uiSettings: uiSettingsMock, - storage: new LocalStorageMock({ - ['discover:dataGridRowHeight']: { - previousRowHeight: 5, - previousConfigRowHeight: 3, - }, - }) as unknown as Storage, - } as DiscoverServices), - } - ); - - expect(result.current.defaultHeight).toEqual({ lineCount: 5 }); - }); - - test('should apply rowHeight from uiSettings', () => { - const { result } = renderHook( - () => { - return useRowHeightsOptions({}); - }, - { - wrapper: getWrapper({ - uiSettings: uiSettingsMock, - storage: new LocalStorageMock({}) as unknown as Storage, - } as unknown as DiscoverServices), - } - ); - - expect(result.current.defaultHeight).toEqual({ - lineCount: CONFIG_ROW_HEIGHT, - }); - }); - - test('should apply rowHeight from uiSettings instead of local storage value, since uiSettings has been changed', () => { - const { result } = renderHook( - () => { - return useRowHeightsOptions({}); - }, - { - wrapper: getWrapper({ - uiSettings: uiSettingsMock, - storage: new LocalStorageMock({ - ['discover:dataGridRowHeight']: { - previousRowHeight: 4, - // different from uiSettings (config), now user changed it to 3, but prev was 4 - previousConfigRowHeight: 4, - }, - }) as unknown as Storage, - } as unknown as DiscoverServices), - } - ); - - expect(result.current.defaultHeight).toEqual({ - lineCount: CONFIG_ROW_HEIGHT, - }); - }); -}); diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts index f567380276354..5af7c2bf1142a 100644 --- a/src/plugins/discover/public/index.ts +++ b/src/plugins/discover/public/index.ts @@ -22,6 +22,11 @@ export type { DiscoverProfileId, DiscoverProfileOptions, RegisterCustomizationProfile, + DiscoverCustomization, + DiscoverCustomizationService, + SearchBarCustomization, + UnifiedHistogramCustomization, + TopNavCustomization, } from './customizations'; export { SEARCH_EMBEDDABLE_TYPE, SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER_ID } from './embeddable'; export { loadSharingDataHelpers } from './utils'; diff --git a/src/plugins/discover/public/kibana_services.ts b/src/plugins/discover/public/kibana_services.ts index 8d261d73696e5..ebab3c97c0cec 100644 --- a/src/plugins/discover/public/kibana_services.ts +++ b/src/plugins/discover/public/kibana_services.ts @@ -12,7 +12,6 @@ import type { ScopedHistory, AppMountParameters } from '@kbn/core/public'; import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { createGetterSetter } from '@kbn/kibana-utils-plugin/public'; import { HistoryLocationState } from './build_services'; -import { DocViewsRegistry } from './services/doc_views/doc_views_registry'; let uiActions: UiActionsStart; export interface UrlTracker { @@ -29,9 +28,6 @@ export const [getHeaderActionMenuMounter, setHeaderActionMenuMounter] = export const [getUrlTracker, setUrlTracker] = createGetterSetter('urlTracker'); -export const [getDocViewsRegistry, setDocViewsRegistry] = - createGetterSetter('DocViewsRegistry'); - /** * Makes sure discover and context are using one instance of history. */ diff --git a/src/plugins/discover/public/mocks.tsx b/src/plugins/discover/public/mocks.tsx index e733e9d32dbee..ae2bc4fa547fd 100644 --- a/src/plugins/discover/public/mocks.tsx +++ b/src/plugins/discover/public/mocks.tsx @@ -15,9 +15,6 @@ export type Start = jest.Mocked; const createSetupContract = (): Setup => { const setupContract: Setup = { - docViews: { - addDocView: jest.fn(), - }, locator: sharePluginMock.createLocator(), }; return setupContract; diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index 6db46f53c35fb..e00d9d29516c7 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { i18n } from '@kbn/i18n'; import React, { ComponentType } from 'react'; import { BehaviorSubject, combineLatest, map } from 'rxjs'; import { @@ -26,7 +25,6 @@ import { SharePluginStart, SharePluginSetup } from '@kbn/share-plugin/public'; import { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public'; import { HomePublicPluginSetup } from '@kbn/home-plugin/public'; import { Start as InspectorPublicPluginStart } from '@kbn/inspector-plugin/public'; -import { EuiSkeletonText } from '@elastic/eui'; import { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; import { SavedObjectsStart } from '@kbn/saved-objects-plugin/public'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public'; @@ -42,15 +40,14 @@ import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-taggin import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import type { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import type { UnifiedDocViewerStart } from '@kbn/unified-doc-viewer-plugin/public'; import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public'; import type { LensPublicStart } from '@kbn/lens-plugin/public'; +import { TRUNCATE_MAX_HEIGHT } from '@kbn/discover-utils'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; -import { DOC_TABLE_LEGACY, TRUNCATE_MAX_HEIGHT } from '@kbn/discover-utils'; +import { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import { PLUGIN_ID } from '../common'; -import { DocViewInput, DocViewInputFn } from './services/doc_views/doc_views_types'; -import { DocViewsRegistry } from './services/doc_views/doc_views_registry'; import { - setDocViewsRegistry, setHeaderActionMenuMounter, setScopedHistory, setUiActions, @@ -60,10 +57,8 @@ import { import { registerFeature } from './register_feature'; import { buildServices } from './build_services'; import { SearchEmbeddableFactory } from './embeddable'; -import { DeferredSpinner } from './components'; import { ViewSavedSearchAction } from './embeddable/view_saved_search_action'; import { injectTruncateStyles } from './utils/truncate_styles'; -import { useDiscoverServices } from './hooks/use_discover_services'; import { initializeKbnUrlTracking } from './utils/initialize_kbn_url_tracking'; import { DiscoverContextAppLocator, @@ -85,24 +80,10 @@ import { type DiscoverContainerProps, } from './components/discover_container'; -const DocViewerLegacyTable = React.lazy( - () => import('./services/doc_views/components/doc_viewer_table/legacy') -); -const DocViewerTable = React.lazy(() => import('./services/doc_views/components/doc_viewer_table')); -const SourceViewer = React.lazy(() => import('./services/doc_views/components/doc_viewer_source')); - /** * @public */ export interface DiscoverSetup { - docViews: { - /** - * Add new doc view shown along with table view and json view in the details of each document in Discover. - * @param docViewRaw - */ - addDocView(docViewRaw: DocViewInput | DocViewInputFn): void; - }; - /** * `share` plugin URL locator for Discover app. Use it to generate links into * Discover application, for example, navigate: @@ -210,9 +191,11 @@ export interface DiscoverStartPlugins { savedObjectsManagement: SavedObjectsManagementPluginStart; savedSearch: SavedSearchPublicPluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; + unifiedDocViewer: UnifiedDocViewerStart; lens: LensPublicStart; contentManagement: ContentManagementPublicStart; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } /** @@ -225,7 +208,6 @@ export class DiscoverPlugin constructor(private readonly initializerContext: PluginInitializerContext) {} private appStateUpdater = new BehaviorSubject(() => ({})); - private docViewsRegistry: DocViewsRegistry | null = null; private stopUrlTracking: (() => void) | undefined = undefined; private profileRegistry = createProfileRegistry(); private locator?: DiscoverAppLocator; @@ -251,59 +233,6 @@ export class DiscoverPlugin ); } - this.docViewsRegistry = new DocViewsRegistry(); - setDocViewsRegistry(this.docViewsRegistry); - this.docViewsRegistry.addDocView({ - title: i18n.translate('discover.docViews.table.tableTitle', { - defaultMessage: 'Table', - }), - order: 10, - component: (props) => { - // eslint-disable-next-line react-hooks/rules-of-hooks - const services = useDiscoverServices(); - const DocView = services.uiSettings.get(DOC_TABLE_LEGACY) - ? DocViewerLegacyTable - : DocViewerTable; - - return ( - - - - } - > - - - ); - }, - }); - this.docViewsRegistry.addDocView({ - title: i18n.translate('discover.docViews.json.jsonTitle', { - defaultMessage: 'JSON', - }), - order: 20, - component: ({ hit, dataView, query, textBasedHits }) => { - return ( - - - - } - > - - - ); - }, - }); - const { setTrackedUrl, restorePreviousUrl, @@ -416,9 +345,6 @@ export class DiscoverPlugin this.registerEmbeddable(core, plugins); return { - docViews: { - addDocView: this.docViewsRegistry.addDocView.bind(this.docViewsRegistry), - }, locator: this.locator, }; } diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer.test.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer.test.tsx deleted file mode 100644 index c7c659c6f84d8..0000000000000 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer.test.tsx +++ /dev/null @@ -1,89 +0,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, shallow } from 'enzyme'; -import { DocViewer } from './doc_viewer'; -import { findTestSubject } from '@elastic/eui/lib/test'; -import { getDocViewsRegistry } from '../../../../kibana_services'; -import { DocViewRenderProps } from '../../doc_views_types'; -import { buildDataTableRecord } from '@kbn/discover-utils'; - -jest.mock('../../../../kibana_services', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let registry: any[] = []; - return { - getDocViewsRegistry: () => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - addDocView(view: any) { - registry.push(view); - }, - getDocViewsSorted() { - return registry; - }, - resetRegistry: () => { - registry = []; - }, - }), - }; -}); - -jest.mock('../../../../hooks/use_discover_services', () => { - return { - useDiscoverServices: { - uiSettings: { - get: jest.fn(), - }, - }, - }; -}); - -beforeEach(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (getDocViewsRegistry() as any).resetRegistry(); - jest.clearAllMocks(); -}); - -test('Render with 3 different tabs', () => { - const registry = getDocViewsRegistry(); - registry.addDocView({ order: 10, title: 'Render function', render: jest.fn() }); - registry.addDocView({ order: 20, title: 'React component', component: () =>
    test
    }); - // @ts-expect-error This should be invalid and will throw an error when rendering - registry.addDocView({ order: 30, title: 'Invalid doc view' }); - - const renderProps = { hit: {} } as DocViewRenderProps; - - const wrapper = shallow(); - - expect(wrapper).toMatchSnapshot(); -}); - -test('Render with 1 tab displaying error message', () => { - function SomeComponent() { - // this is just a placeholder - return null; - } - - const registry = getDocViewsRegistry(); - registry.addDocView({ - order: 10, - title: 'React component', - component: SomeComponent, - }); - - const renderProps = { - hit: buildDataTableRecord({ _index: 't', _id: '1' }), - } as DocViewRenderProps; - const errorMsg = 'Catch me if you can!'; - - const wrapper = mount(); - const error = new Error(errorMsg); - wrapper.find(SomeComponent).simulateError(error); - const errorMsgComponent = findTestSubject(wrapper, 'docViewerError'); - expect(errorMsgComponent.text()).toMatch(new RegExp(`${errorMsg}`)); -}); diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index bd06f793a6447..d6bbbd0eed9f0 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -30,7 +30,7 @@ import { TRUNCATE_MAX_HEIGHT, SHOW_FIELD_STATISTICS, ROW_HEIGHT_OPTION, - ENABLE_SQL, + ENABLE_ESQL, } from '@kbn/discover-utils'; import { DEFAULT_ROWS_PER_PAGE, ROWS_PER_PAGE_OPTIONS } from '../common/constants'; @@ -308,18 +308,18 @@ export const getUiSettings: (docLinks: DocLinksServiceSetup) => Record` + - i18n.translate('discover.advancedSettings.enableSQL.discussLinkText', { + i18n.translate('discover.advancedSettings.enableESQL.discussLinkText', { defaultMessage: 'discuss.elastic.co/c/elastic-stack/kibana', }) + '
    ', diff --git a/src/plugins/discover/tsconfig.json b/src/plugins/discover/tsconfig.json index df92ba4c9070c..3328073a026e7 100644 --- a/src/plugins/discover/tsconfig.json +++ b/src/plugins/discover/tsconfig.json @@ -51,8 +51,6 @@ "@kbn/shared-ux-page-analytics-no-data", "@kbn/alerting-plugin", "@kbn/ui-theme", - "@kbn/react-field", - "@kbn/monaco", "@kbn/config-schema", "@kbn/storybook", "@kbn/shared-ux-router", @@ -65,12 +63,15 @@ "@kbn/core-application-browser", "@kbn/core-saved-objects-server", "@kbn/discover-utils", - "@kbn/field-types", "@kbn/search-response-warnings", "@kbn/content-management-plugin", + "@kbn/unified-doc-viewer", + "@kbn/unified-doc-viewer-plugin", "@kbn/serverless", "@kbn/react-kibana-mount", - "@kbn/react-kibana-context-render" + "@kbn/react-kibana-context-render", + "@kbn/unified-data-table", + "@kbn/no-data-page-plugin" ], "exclude": [ "target/**/*" diff --git a/src/plugins/expressions/README.asciidoc b/src/plugins/expressions/README.asciidoc index 569c06c7e61bb..6ea4d7f49cbd8 100644 --- a/src/plugins/expressions/README.asciidoc +++ b/src/plugins/expressions/README.asciidoc @@ -44,6 +44,8 @@ filters [role="screenshot"] image::https://user-images.githubusercontent.com/9773803/74162514-3250a880-4c21-11ea-9e68-86f66862a183.png[] +//// +// Commenting out due to broken links === API documentation ==== Server API @@ -57,3 +59,4 @@ https://github.com/elastic/kibana/blob/main/docs/development/plugins/expressions ==== Other documentation https://www.elastic.co/guide/en/kibana/current/canvas-function-arguments.html[See Canvas documentation about expressions] +//// diff --git a/src/plugins/expressions/common/expression_types/specs/datatable.ts b/src/plugins/expressions/common/expression_types/specs/datatable.ts index 38b21addd5968..fbba26f3d4dc8 100644 --- a/src/plugins/expressions/common/expression_types/specs/datatable.ts +++ b/src/plugins/expressions/common/expression_types/specs/datatable.ts @@ -131,6 +131,7 @@ export interface Datatable { columns: DatatableColumn[]; meta?: DatatableMeta; rows: DatatableRow[]; + warning?: string; } export interface SerializedDatatable extends Datatable { diff --git a/src/plugins/files/server/blob_storage_service/adapters/es/content_stream/content_stream.ts b/src/plugins/files/server/blob_storage_service/adapters/es/content_stream/content_stream.ts index aeb547a1bf6f8..a0c5316abf2a2 100644 --- a/src/plugins/files/server/blob_storage_service/adapters/es/content_stream/content_stream.ts +++ b/src/plugins/files/server/blob_storage_service/adapters/es/content_stream/content_stream.ts @@ -271,6 +271,7 @@ export class ContentStream extends Duplex { * of holding, at most, 2 full chunks in memory. */ private indexRequestBuffer: undefined | IndexRequestParams; + private async writeChunk(data: Buffer) { const chunkId = this.getChunkId(this.chunksWritten); diff --git a/src/plugins/files/server/blob_storage_service/adapters/es/es.ts b/src/plugins/files/server/blob_storage_service/adapters/es/es.ts index 106b7251fed23..a08d220b1c8e2 100644 --- a/src/plugins/files/server/blob_storage_service/adapters/es/es.ts +++ b/src/plugins/files/server/blob_storage_service/adapters/es/es.ts @@ -183,11 +183,19 @@ export class ElasticsearchBlobStorageClient implements BlobStorageClient { } public async download({ id, size }: { id: string; size?: number }): Promise { + // The refresh interval is set to 10s. To avoid throwing an error if the user tries to download a file + // right after uploading it, we refresh the index before downloading the file. + await this.esClient.indices.refresh({ index: this.index }); + return this.getReadableContentStream(id, size); } public async delete(id: string): Promise { try { + // The refresh interval is set to 10s. To avoid throwing an error if the user tries to delete a file + // right after uploading it, we refresh the index before deleting the file. + await this.esClient.indices.refresh({ index: this.index }); + const dest = getWritableContentStream({ id, client: this.esClient, diff --git a/src/plugins/files/server/blob_storage_service/adapters/es/integration_tests/es.test.ts b/src/plugins/files/server/blob_storage_service/adapters/es/integration_tests/es.test.ts index d2c13bc7d76ff..1e6b357cbf874 100644 --- a/src/plugins/files/server/blob_storage_service/adapters/es/integration_tests/es.test.ts +++ b/src/plugins/files/server/blob_storage_service/adapters/es/integration_tests/es.test.ts @@ -22,6 +22,7 @@ describe('Elasticsearch blob storage', () => { let esBlobStorage: ElasticsearchBlobStorageClient; let esClient: ElasticsearchClient; let esGetSpy: jest.SpyInstance; + let esRefreshIndexSpy: jest.SpyInstance; beforeAll(async () => { ElasticsearchBlobStorageClient.configureConcurrentUpload(Infinity); @@ -48,6 +49,7 @@ describe('Elasticsearch blob storage', () => { beforeEach(() => { esBlobStorage = createEsBlobStorage(); esGetSpy = jest.spyOn(esClient, 'get'); + esRefreshIndexSpy = jest.spyOn(esClient.indices, 'refresh'); }); afterEach(async () => { @@ -105,7 +107,9 @@ describe('Elasticsearch blob storage', () => { esBlobStorage = createEsBlobStorage({ chunkSize: '1024B' }); const { id } = await esBlobStorage.upload(Readable.from([fileString])); expect(await getAllDocCount()).toMatchObject({ count: 37 }); + esRefreshIndexSpy.mockReset(); const rs = await esBlobStorage.download({ id }); + expect(esRefreshIndexSpy).toHaveBeenCalled(); // Make sure we refresh the index before downloading the chunks const chunks: string[] = []; for await (const chunk of rs) { chunks.push(chunk); @@ -137,7 +141,9 @@ describe('Elasticsearch blob storage', () => { const { id } = await esBlobStorage.upload(Readable.from([fileString])); const { id: id2 } = await esBlobStorage.upload(Readable.from([fileString2])); expect(await getAllDocCount()).toMatchObject({ count: 10 }); + esRefreshIndexSpy.mockReset(); await esBlobStorage.delete(id); + expect(esRefreshIndexSpy).toHaveBeenCalled(); // Make sure we refresh the index before deleting the chunks expect(await getAllDocCount()).toMatchObject({ count: 2 }); // Now we check that the other file is still intact const rs = await esBlobStorage.download({ id: id2 }); diff --git a/src/plugins/files/server/file_client/integration_tests/es_file_client.test.ts b/src/plugins/files/server/file_client/integration_tests/es_file_client.test.ts index 91d9e543ec850..cbe80422e388b 100644 --- a/src/plugins/files/server/file_client/integration_tests/es_file_client.test.ts +++ b/src/plugins/files/server/file_client/integration_tests/es_file_client.test.ts @@ -13,15 +13,34 @@ import { createEsFileClient } from '../create_es_file_client'; import { FileClient } from '../types'; import { FileMetadata } from '../../../common'; -// FLAKY: https://github.com/elastic/kibana/issues/144505 -// FLAKY: https://github.com/elastic/kibana/issues/144506 -describe.skip('ES-index-backed file client', () => { +describe('ES-index-backed file client', () => { let esClient: TestEnvironmentUtils['esClient']; let fileClient: FileClient; let testHarness: TestEnvironmentUtils; const blobStorageIndex = '.kibana-test-blob'; const metadataIndex = '.kibana-test-metadata'; + const deleteFile = async ({ + id, + hasContent, + refreshIndex = true, + }: { + id: string; + hasContent?: boolean; + refreshIndex?: boolean; + }) => { + if (refreshIndex) { + try { + // Make sure to refresh the index before deleting the file to avoid an conflict error thrown by + // ES when deleting by query documents that don't exist yet. + await esClient.indices.refresh({ index: blobStorageIndex }); + } catch (e) { + // Silently fail if the index does not exist + } + } + await fileClient.delete({ id, hasContent }); + }; + beforeAll(async () => { testHarness = await setupIntegrationEnvironment(); ({ esClient } = testHarness); @@ -57,7 +76,7 @@ describe.skip('ES-index-backed file client', () => { name: 'cool name', }) ); - await fileClient.delete({ id: file.id, hasContent: false }); + await deleteFile({ id: file.id, hasContent: false }); }); test('uploads and downloads file content', async () => { @@ -75,7 +94,7 @@ describe.skip('ES-index-backed file client', () => { } expect(Buffer.concat(chunks).toString('utf-8')).toBe('test'); - await fileClient.delete({ id: file.id, hasContent: true }); + await deleteFile({ id: file.id, hasContent: true }); }); test('searches across files', async () => { @@ -150,10 +169,12 @@ describe.skip('ES-index-backed file client', () => { ); } + await esClient.indices.refresh({ index: blobStorageIndex }); + await Promise.all([ - fileClient.delete({ id: id1 }), - fileClient.delete({ id: id2 }), - fileClient.delete({ id: file3.id }), + deleteFile({ id: id1, refreshIndex: false }), + deleteFile({ id: id2, refreshIndex: false }), + deleteFile({ id: file3.id, refreshIndex: false }), ]); }); @@ -197,9 +218,11 @@ describe.skip('ES-index-backed file client', () => { }) ); + await esClient.indices.refresh({ index: blobStorageIndex }); + await Promise.all([ - fileClient.delete({ id: id1, hasContent: false }), - fileClient.delete({ id: id2, hasContent: false }), + deleteFile({ id: id1, hasContent: false, refreshIndex: false }), + deleteFile({ id: id2, hasContent: false, refreshIndex: false }), ]); }); }); diff --git a/src/plugins/interactive_setup/public/progress_indicator.tsx b/src/plugins/interactive_setup/public/progress_indicator.tsx index 9fee7e6da7110..5da14e8081555 100644 --- a/src/plugins/interactive_setup/public/progress_indicator.tsx +++ b/src/plugins/interactive_setup/public/progress_indicator.tsx @@ -27,14 +27,7 @@ function isKibanaPastPreboot(response?: Response, body?: StatusResponse) { if (!response?.headers.get('content-type')?.includes('application/json')) { return false; } - - return ( - // Status endpoint may require authentication after `preboot` stage. - response?.status === 401 || - // We're only interested in the availability of the critical core services. - (body?.status?.core?.elasticsearch?.level === 'available' && - body?.status?.core?.savedObjects?.level === 'available') - ); + return body?.status?.overall?.level === 'available'; } export const ProgressIndicator: FunctionComponent = ({ onSuccess }) => { diff --git a/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap b/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap index bfbc661cad9b0..0a3ba18656cae 100644 --- a/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap +++ b/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap @@ -126,6 +126,7 @@ exports[` is rendered 1`] = ` >
    = ({ const { CopyButton } = useCopy({ isCopyable, value }); return ( -
    +
    {renderPrompt()} diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts index c335f56998ce3..2b43cbe6c5a1d 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts @@ -139,7 +139,7 @@ export const applicationUsageSchema = { enterpriseSearchApplications: commonSchema, enterpriseSearchEsre: commonSchema, enterpriseSearchVectorSearch: commonSchema, - elasticsearch: commonSchema, + enterpriseSearchElasticsearch: commonSchema, appSearch: commonSchema, workplaceSearch: commonSchema, searchExperiences: commonSchema, @@ -154,6 +154,7 @@ export const applicationUsageSchema = { maps: commonSchema, ml: commonSchema, monitoring: commonSchema, + 'observability-log-explorer': commonSchema, 'observability-overview': commonSchema, observabilityOnboarding: commonSchema, observabilityAIAssistant: commonSchema, diff --git a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts index 8a960fa05ebf6..8d5f0db7a669d 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts @@ -923,6 +923,20 @@ export function getCoreUsageCollector( 'How many times this API has been called without the `createNewCopiesEnabled` option.', }, }, + 'apiCalls.savedObjectsImport.compatibilityModeEnabled.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called with the `compatibilityMode` option.', + }, + }, + 'apiCalls.savedObjectsImport.compatibilityModeEnabled.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called without the `compatibilityMode` option.', + }, + }, 'apiCalls.savedObjectsImport.overwriteEnabled.yes': { type: 'long', _meta: { diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index 9822d2985bced..f17f1e1cc42e8 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -501,7 +501,7 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, - 'discover:enableSql': { + 'discover:enableESQL': { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index 1b5f84019eb7b..902190f0cf675 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -34,7 +34,7 @@ export interface UsageStats { 'discover:searchFieldsFromSource': boolean; 'discover:showFieldStatistics': boolean; 'discover:showMultiFields': boolean; - 'discover:enableSql': boolean; + 'discover:enableESQL': boolean; 'discover:maxDocFieldsDisplayed': number; 'securitySolution:rulesTableRefresh': string; 'observability:enableInspectEsQueries': boolean; diff --git a/src/plugins/no_data_page/README.md b/src/plugins/no_data_page/README.md new file mode 100755 index 0000000000000..a516e3274ff3f --- /dev/null +++ b/src/plugins/no_data_page/README.md @@ -0,0 +1,3 @@ +# No Data Page + +Helps to globally configure the no data page components diff --git a/src/plugins/no_data_page/config.ts b/src/plugins/no_data_page/config.ts new file mode 100644 index 0000000000000..8fae1aad10aaa --- /dev/null +++ b/src/plugins/no_data_page/config.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { schema, TypeOf, offeringBasedSchema } from '@kbn/config-schema'; + +export const configSchema = schema.object({ + analyticsNoDataPageFlavor: offeringBasedSchema({ + serverless: schema.oneOf( + [schema.oneOf([schema.literal('kibana'), schema.literal('serverless_search')])], + { defaultValue: 'kibana' as const } + ), + }), +}); +export type NoDataPageConfig = TypeOf; diff --git a/src/plugins/no_data_page/jest.config.js b/src/plugins/no_data_page/jest.config.js new file mode 100644 index 0000000000000..546031bc12414 --- /dev/null +++ b/src/plugins/no_data_page/jest.config.js @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/src/plugins/no_data_page'], + coverageDirectory: '/target/kibana-coverage/jest/src/plugins/no_data_page', + coverageReporters: ['text', 'html'], + collectCoverageFrom: ['/src/plugins/no_data_page/{common,public,server}/**/*.{ts,tsx}'], +}; diff --git a/src/plugins/no_data_page/kibana.jsonc b/src/plugins/no_data_page/kibana.jsonc new file mode 100644 index 0000000000000..202917173b7a4 --- /dev/null +++ b/src/plugins/no_data_page/kibana.jsonc @@ -0,0 +1,10 @@ +{ + "type": "plugin", + "id": "@kbn/no-data-page-plugin", + "owner": "@elastic/appex-sharedux", + "plugin": { + "id": "noDataPage", + "server": true, + "browser": true + } +} diff --git a/src/plugins/no_data_page/public/index.ts b/src/plugins/no_data_page/public/index.ts new file mode 100644 index 0000000000000..28dfcd6044403 --- /dev/null +++ b/src/plugins/no_data_page/public/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { PluginInitializerContext } from '@kbn/core-plugins-browser'; +import { NoDataPagePlugin } from './plugin'; + +export function plugin(ctx: PluginInitializerContext) { + return new NoDataPagePlugin(ctx); +} + +export type { NoDataPagePluginSetup, NoDataPagePluginStart } from './types'; diff --git a/src/plugins/no_data_page/public/plugin.ts b/src/plugins/no_data_page/public/plugin.ts new file mode 100644 index 0000000000000..740f796f4f395 --- /dev/null +++ b/src/plugins/no_data_page/public/plugin.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 type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; +import type { NoDataPagePluginSetup, NoDataPagePluginStart } from './types'; +import type { NoDataPageConfig } from '../config'; + +export class NoDataPagePlugin implements Plugin { + constructor(private initializerContext: PluginInitializerContext) {} + + public setup(core: CoreSetup): NoDataPagePluginSetup { + return { + getAnalyticsNoDataPageFlavor: () => { + return this.initializerContext.config.get().analyticsNoDataPageFlavor; + }, + }; + } + + public start(core: CoreStart): NoDataPagePluginStart { + return { + getAnalyticsNoDataPageFlavor: () => { + return this.initializerContext.config.get().analyticsNoDataPageFlavor; + }, + }; + } +} diff --git a/src/plugins/no_data_page/public/types.ts b/src/plugins/no_data_page/public/types.ts new file mode 100644 index 0000000000000..c9523f7fcd93a --- /dev/null +++ b/src/plugins/no_data_page/public/types.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 interface NoDataPagePluginSetup { + getAnalyticsNoDataPageFlavor: () => 'kibana' | 'serverless_search'; +} + +export type NoDataPagePluginStart = NoDataPagePluginSetup; diff --git a/src/plugins/no_data_page/server/index.ts b/src/plugins/no_data_page/server/index.ts new file mode 100644 index 0000000000000..ba02a016a9676 --- /dev/null +++ b/src/plugins/no_data_page/server/index.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 { PluginConfigDescriptor } from '@kbn/core-plugins-server'; + +import { configSchema, NoDataPageConfig } from '../config'; + +export const config: PluginConfigDescriptor = { + exposeToBrowser: { + analyticsNoDataPageFlavor: true, + }, + schema: configSchema, +}; + +export function plugin() { + return new (class NoDataPagePlugin { + setup() {} + start() {} + })(); +} diff --git a/src/plugins/no_data_page/tsconfig.json b/src/plugins/no_data_page/tsconfig.json new file mode 100644 index 0000000000000..bab1c8c23edfb --- /dev/null +++ b/src/plugins/no_data_page/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types" + }, + "include": ["common/**/*", "public/**/*", "server/**/*", "config.ts"], + "kbn_references": [ + "@kbn/core", + "@kbn/core-plugins-browser", + "@kbn/core-plugins-server", + "@kbn/config-schema", + ], + "exclude": ["target/**/*"] +} diff --git a/src/plugins/telemetry/common/types/v2.ts b/src/plugins/telemetry/common/types/v2.ts index dc90ad3d242a6..db64c45d96710 100644 --- a/src/plugins/telemetry/common/types/v2.ts +++ b/src/plugins/telemetry/common/types/v2.ts @@ -6,6 +6,8 @@ * Side Public License, v 1. */ +import type { TelemetryConfigLabels } from '../../server/config'; + export interface Telemetry { /** Whether telemetry is enabled */ enabled?: boolean | null; @@ -24,6 +26,7 @@ export interface FetchTelemetryConfigResponse { optIn: boolean | null; sendUsageFrom: 'server' | 'browser'; telemetryNotifyUserAboutOptInDefault: boolean; + labels: TelemetryConfigLabels; } export interface FetchLastReportedResponse { diff --git a/src/plugins/telemetry/kibana.jsonc b/src/plugins/telemetry/kibana.jsonc index 147c7ac8b84cd..44162c1189c2e 100644 --- a/src/plugins/telemetry/kibana.jsonc +++ b/src/plugins/telemetry/kibana.jsonc @@ -6,6 +6,7 @@ "id": "telemetry", "server": true, "browser": true, + "enabledOnAnonymousPages": true, "requiredPlugins": [ "telemetryCollectionManager", "usageCollection", diff --git a/src/plugins/telemetry/public/plugin.ts b/src/plugins/telemetry/public/plugin.ts index c0d0faf0819b0..6300a56486169 100644 --- a/src/plugins/telemetry/public/plugin.ts +++ b/src/plugins/telemetry/public/plugin.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import type { ApmBase } from '@elastic/apm-rum'; import type { Plugin, CoreStart, @@ -23,7 +24,8 @@ import type { import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; import { ElasticV3BrowserShipper } from '@kbn/analytics-shippers-elastic-v3-browser'; -import { of } from 'rxjs'; +import { BehaviorSubject, map, tap } from 'rxjs'; +import type { TelemetryConfigLabels } from '../server/config'; import { FetchTelemetryConfigRoute, INTERNAL_VERSION } from '../common/routes'; import type { v2 } from '../common/types'; import { TelemetrySender, TelemetryService, TelemetryNotifications } from './services'; @@ -88,6 +90,12 @@ interface TelemetryPluginStartDependencies { screenshotMode: ScreenshotModePluginStart; } +declare global { + interface Window { + elasticApm?: ApmBase; + } +} + /** * Public-exposed configuration */ @@ -131,6 +139,7 @@ export class TelemetryPlugin { private readonly currentKibanaVersion: string; private readonly config: TelemetryPluginConfig; + private readonly telemetryLabels$: BehaviorSubject; private telemetrySender?: TelemetrySender; private telemetryNotifications?: TelemetryNotifications; private telemetryService?: TelemetryService; @@ -139,6 +148,7 @@ export class TelemetryPlugin constructor(initializerContext: PluginInitializerContext) { this.currentKibanaVersion = initializerContext.env.packageInfo.version; this.config = initializerContext.config.get(); + this.telemetryLabels$ = new BehaviorSubject(this.config.labels); } public setup( @@ -163,7 +173,14 @@ export class TelemetryPlugin analytics.registerContextProvider({ name: 'telemetry labels', - context$: of({ labels: this.config.labels }), + context$: this.telemetryLabels$.pipe( + tap((labels) => { + // Hack to update the APM agent's labels. + // In the future we might want to expose APM as a core service to make reporting metrics much easier. + window.elasticApm?.addLabels(labels); + }), + map((labels) => ({ labels })) + ), schema: { labels: { type: 'pass_through', @@ -230,11 +247,6 @@ export class TelemetryPlugin this.telemetryNotifications = telemetryNotifications; application.currentAppId$.subscribe(async () => { - const isUnauthenticated = this.getIsUnauthenticated(http); - if (isUnauthenticated) { - return; - } - // Refresh and get telemetry config const updatedConfig = await this.refreshConfig(http); @@ -242,6 +254,11 @@ export class TelemetryPlugin global: { enabled: this.telemetryService!.isOptedIn && !screenshotMode.isScreenshotMode() }, }); + const isUnauthenticated = this.getIsUnauthenticated(http); + if (isUnauthenticated) { + return; + } + const telemetryBanner = updatedConfig?.banner; this.maybeStartTelemetryPoller(); @@ -285,6 +302,9 @@ export class TelemetryPlugin if (this.telemetryService) { this.telemetryService.config = updatedConfig; } + + this.telemetryLabels$.next(updatedConfig.labels); + return updatedConfig; } @@ -328,8 +348,16 @@ export class TelemetryPlugin * @private */ private async fetchUpdatedConfig(http: HttpStart | HttpSetup): Promise { - const { allowChangingOptInStatus, optIn, sendUsageFrom, telemetryNotifyUserAboutOptInDefault } = - await http.get(FetchTelemetryConfigRoute, INTERNAL_VERSION); + const { + allowChangingOptInStatus, + optIn, + sendUsageFrom, + telemetryNotifyUserAboutOptInDefault, + labels, + } = await http.get( + FetchTelemetryConfigRoute, + INTERNAL_VERSION + ); return { ...this.config, @@ -337,6 +365,7 @@ export class TelemetryPlugin optIn, sendUsageFrom, telemetryNotifyUserAboutOptInDefault, + labels, userCanChangeSettings: this.canUserChangeSettings, }; } diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index de4f1fae8f675..e90ab7c9d6a2b 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -2622,7 +2622,7 @@ } } }, - "elasticsearch": { + "enterpriseSearchElasticsearch": { "properties": { "appId": { "type": "keyword", @@ -4587,6 +4587,137 @@ } } }, + "observability-log-explorer": { + "properties": { + "appId": { + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } + }, + "viewId": { + "type": "keyword", + "_meta": { + "description": "Always `main`" + } + }, + "clicks_total": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } + }, + "clicks_7_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } + }, + "clicks_30_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } + }, + "clicks_90_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } + }, + "minutes_on_screen_total": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } + }, + "minutes_on_screen_7_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } + }, + "minutes_on_screen_30_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } + }, + "minutes_on_screen_90_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } + }, + "views": { + "type": "array", + "items": { + "properties": { + "appId": { + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } + }, + "viewId": { + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } + }, + "clicks_total": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } + }, + "clicks_7_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } + }, + "clicks_30_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } + }, + "clicks_90_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } + }, + "minutes_on_screen_total": { + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } + }, + "minutes_on_screen_7_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } + }, + "minutes_on_screen_30_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } + }, + "minutes_on_screen_90_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } + } + } + } + } + } + }, "observability-overview": { "properties": { "appId": { @@ -8241,6 +8372,18 @@ "description": "How many times this API has been called without the `createNewCopiesEnabled` option." } }, + "apiCalls.savedObjectsImport.compatibilityModeEnabled.yes": { + "type": "long", + "_meta": { + "description": "How many times this API has been called with the `compatibilityMode` option." + } + }, + "apiCalls.savedObjectsImport.compatibilityModeEnabled.no": { + "type": "long", + "_meta": { + "description": "How many times this API has been called without the `compatibilityMode` option." + } + }, "apiCalls.savedObjectsImport.overwriteEnabled.yes": { "type": "long", "_meta": { @@ -9798,7 +9941,7 @@ "description": "Non-default value of setting." } }, - "discover:enableSql": { + "discover:enableESQL": { "type": "boolean", "_meta": { "description": "Non-default value of setting." diff --git a/src/plugins/telemetry/server/config/config.ts b/src/plugins/telemetry/server/config/config.ts index 9ac63b8937ba3..3bb428a948ec5 100644 --- a/src/plugins/telemetry/server/config/config.ts +++ b/src/plugins/telemetry/server/config/config.ts @@ -56,6 +56,9 @@ export const config: PluginConfigDescriptor = { hidePrivacyStatement: true, labels: true, }, + dynamicConfig: { + labels: true, + }, deprecations: () => [ (cfg) => { if (cfg.telemetry?.enabled === false) { diff --git a/src/plugins/telemetry/server/config/telemetry_labels.ts b/src/plugins/telemetry/server/config/telemetry_labels.ts index f78b216b214e8..b55103839f4dc 100644 --- a/src/plugins/telemetry/server/config/telemetry_labels.ts +++ b/src/plugins/telemetry/server/config/telemetry_labels.ts @@ -27,6 +27,7 @@ export const labelsSchema = schema.object( testBuildId: schema.maybe(schema.string()), testJobId: schema.maybe(schema.string()), ciBuildName: schema.maybe(schema.string()), + performancePhase: schema.maybe(schema.string()), /** * The serverless project type. * Flagging it as maybe because these settings should never affect how Kibana runs. diff --git a/src/plugins/telemetry/server/plugin.ts b/src/plugins/telemetry/server/plugin.ts index ddbf7704d3838..6ce2a875e8549 100644 --- a/src/plugins/telemetry/server/plugin.ts +++ b/src/plugins/telemetry/server/plugin.ts @@ -40,6 +40,7 @@ import type { import type { SecurityPluginStart } from '@kbn/security-plugin/server'; import { SavedObjectsClient } from '@kbn/core/server'; +import apm from 'elastic-apm-node'; import { type TelemetrySavedObject, getTelemetrySavedObject, @@ -173,12 +174,18 @@ export class TelemetryPlugin implements Plugin({ name: 'telemetry labels', - context$: this.config$.pipe(map(({ labels }) => ({ labels }))), + context$: this.config$.pipe( + map(({ labels }) => ({ labels })), + tap(({ labels }) => + Object.entries(labels).forEach(([key, value]) => apm.setGlobalLabel(key, value)) + ) + ), schema: { labels: { type: 'pass_through', _meta: { - description: 'Custom labels added to the telemetry.labels config in the kibana.yml', + description: + 'Custom labels added to the telemetry.labels config in the kibana.yml. Validated and limited to a known set of labels.', }, }, }, diff --git a/src/plugins/telemetry/server/routes/telemetry_config.ts b/src/plugins/telemetry/server/routes/telemetry_config.ts index 37daef537b568..d62566bdc3563 100644 --- a/src/plugins/telemetry/server/routes/telemetry_config.ts +++ b/src/plugins/telemetry/server/routes/telemetry_config.ts @@ -10,6 +10,7 @@ import { type Observable, firstValueFrom } from 'rxjs'; import type { IRouter, SavedObjectsClient } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; import { RequestHandler } from '@kbn/core-http-server'; +import { labelsSchema } from '../config/telemetry_labels'; import type { TelemetryConfigType } from '../config'; import { v2 } from '../../common/types'; import { @@ -70,6 +71,7 @@ export function registerTelemetryConfigRoutes({ optIn, sendUsageFrom, telemetryNotifyUserAboutOptInDefault, + labels: config.labels, }; return res.ok({ body }); @@ -83,6 +85,7 @@ export function registerTelemetryConfigRoutes({ optIn: schema.oneOf([schema.boolean(), schema.literal(null)]), sendUsageFrom: schema.oneOf([schema.literal('server'), schema.literal('browser')]), telemetryNotifyUserAboutOptInDefault: schema.boolean(), + labels: labelsSchema, }), }, }, @@ -90,7 +93,11 @@ export function registerTelemetryConfigRoutes({ // Register the internal versioned API router.versioned - .get({ access: 'internal', path: FetchTelemetryConfigRoute }) + .get({ + access: 'internal', + path: FetchTelemetryConfigRoute, + options: { authRequired: 'optional' }, + }) // Just because it used to be /v2/, we are creating identical v1 and v2. .addVersion({ version: '1', validate: v2Validations }, v2Handler) .addVersion({ version: '2', validate: v2Validations }, v2Handler); diff --git a/src/plugins/text_based_languages/kibana.jsonc b/src/plugins/text_based_languages/kibana.jsonc index 472560aa3b488..f22a87185b54c 100644 --- a/src/plugins/text_based_languages/kibana.jsonc +++ b/src/plugins/text_based_languages/kibana.jsonc @@ -6,6 +6,14 @@ "id": "textBasedLanguages", "server": false, "browser": true, + "optionalPlugins": [ + "indexManagement" + ], + "requiredPlugins": [ + "data", + "expressions", + "dataViews" + ], "requiredBundles": [ "kibanaReact", ] diff --git a/src/plugins/text_based_languages/public/create_editor.tsx b/src/plugins/text_based_languages/public/create_editor.tsx index 1fefff765f9b2..534d86420b74d 100644 --- a/src/plugins/text_based_languages/public/create_editor.tsx +++ b/src/plugins/text_based_languages/public/create_editor.tsx @@ -27,7 +27,7 @@ export const TextBasedLangEditor = (props: TextBasedLanguagesEditorProps) => { return ( diff --git a/src/plugins/text_based_languages/public/kibana_services.ts b/src/plugins/text_based_languages/public/kibana_services.ts index 01f0dd4a823d3..8592904a69370 100644 --- a/src/plugins/text_based_languages/public/kibana_services.ts +++ b/src/plugins/text_based_languages/public/kibana_services.ts @@ -7,17 +7,25 @@ */ import { BehaviorSubject } from 'rxjs'; - -import { CoreStart } from '@kbn/core/public'; +import type { CoreStart } from '@kbn/core/public'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; +import { IndexManagementPluginSetup } from '@kbn/index-management-plugin/public'; export let core: CoreStart; -const servicesReady$ = new BehaviorSubject<{ core: CoreStart; darkMode: boolean } | undefined>( - undefined -); +interface ServiceDeps { + core: CoreStart; + darkMode: boolean; + dataViews: DataViewsPublicPluginStart; + expressions: ExpressionsStart; + indexManagementApiService?: IndexManagementPluginSetup['apiService']; +} + +const servicesReady$ = new BehaviorSubject(undefined); export const untilPluginStartServicesReady = () => { if (servicesReady$.value) return Promise.resolve(servicesReady$.value); - return new Promise<{ core: CoreStart; darkMode: boolean }>((resolve) => { + return new Promise((resolve) => { const subscription = servicesReady$.subscribe((deps) => { if (deps) { subscription.unsubscribe(); @@ -27,9 +35,20 @@ export const untilPluginStartServicesReady = () => { }); }; -export const setKibanaServices = (kibanaCore: CoreStart) => { +export const setKibanaServices = ( + kibanaCore: CoreStart, + dataViews: DataViewsPublicPluginStart, + expressions: ExpressionsStart, + indexManagement?: IndexManagementPluginSetup +) => { core = kibanaCore; core.theme.theme$.subscribe(({ darkMode }) => { - servicesReady$.next({ core, darkMode }); + servicesReady$.next({ + core, + darkMode, + dataViews, + expressions, + indexManagementApiService: indexManagement?.apiService, + }); }); }; diff --git a/src/plugins/text_based_languages/public/plugin.ts b/src/plugins/text_based_languages/public/plugin.ts index f983baf517f8c..d496bdfe30f99 100755 --- a/src/plugins/text_based_languages/public/plugin.ts +++ b/src/plugins/text_based_languages/public/plugin.ts @@ -6,16 +6,31 @@ * Side Public License, v 1. */ -import { Plugin, CoreStart } from '@kbn/core/public'; +import type { Plugin, CoreStart, CoreSetup } from '@kbn/core/public'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; +import type { IndexManagementPluginSetup } from '@kbn/index-management-plugin/public'; import { setKibanaServices } from './kibana_services'; +interface TextBasedLanguagesPluginStart { + dataViews: DataViewsPublicPluginStart; + expressions: ExpressionsStart; +} + +interface TextBasedLanguagesPluginSetup { + indexManagement: IndexManagementPluginSetup; +} + export class TextBasedLanguagesPlugin implements Plugin<{}, void> { - public setup() { + private indexManagement?: IndexManagementPluginSetup; + + public setup(_: CoreSetup, { indexManagement }: TextBasedLanguagesPluginSetup) { + this.indexManagement = indexManagement; return {}; } - public start(core: CoreStart): void { - setKibanaServices(core); + public start(core: CoreStart, { dataViews, expressions }: TextBasedLanguagesPluginStart): void { + setKibanaServices(core, dataViews, expressions, this.indexManagement); } public stop() {} diff --git a/src/plugins/text_based_languages/tsconfig.json b/src/plugins/text_based_languages/tsconfig.json index d8b5cbd5e965b..152a2aba25c6b 100644 --- a/src/plugins/text_based_languages/tsconfig.json +++ b/src/plugins/text_based_languages/tsconfig.json @@ -13,6 +13,9 @@ "@kbn/text-based-editor", "@kbn/kibana-react-plugin", "@kbn/core", + "@kbn/expressions-plugin", + "@kbn/data-views-plugin", + "@kbn/index-management-plugin", ], "exclude": [ "target/**/*", diff --git a/src/plugins/unified_doc_viewer/README.md b/src/plugins/unified_doc_viewer/README.md new file mode 100644 index 0000000000000..5a88d60f00444 --- /dev/null +++ b/src/plugins/unified_doc_viewer/README.md @@ -0,0 +1,3 @@ +# unifiedDocViewer + +This plugin contains services reliant on the plugin lifecycle for the unified doc viewer component (see @kbn/unified-doc-viewer). \ No newline at end of file diff --git a/src/plugins/unified_doc_viewer/jest.config.js b/src/plugins/unified_doc_viewer/jest.config.js new file mode 100644 index 0000000000000..5250be53c79a6 --- /dev/null +++ b/src/plugins/unified_doc_viewer/jest.config.js @@ -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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/src/plugins/unified_doc_viewer'], + coverageDirectory: '/target/kibana-coverage/jest/src/plugins/unified_doc_viewer', + coverageReporters: ['text', 'html'], + collectCoverageFrom: [ + '/src/plugins/unified_doc_viewer/{common,public,server}/**/*.{ts,tsx}', + ], +}; diff --git a/src/plugins/unified_doc_viewer/kibana.jsonc b/src/plugins/unified_doc_viewer/kibana.jsonc new file mode 100644 index 0000000000000..deb19cf85c0e4 --- /dev/null +++ b/src/plugins/unified_doc_viewer/kibana.jsonc @@ -0,0 +1,13 @@ +{ + "type": "plugin", + "id": "@kbn/unified-doc-viewer-plugin", + "owner": "@elastic/kibana-data-discovery", + "description": "This plugin contains services reliant on the plugin lifecycle for the unified doc viewer component (see @kbn/unified-doc-viewer).", + "plugin": { + "id": "unifiedDocViewer", + "server": false, + "browser": true, + "requiredBundles": ["kibanaUtils", "kibanaReact"], + "requiredPlugins": ["data", "fieldFormats"], + } +} diff --git a/src/plugins/unified_doc_viewer/public/__mocks__/index.ts b/src/plugins/unified_doc_viewer/public/__mocks__/index.ts new file mode 100644 index 0000000000000..d15c62a75d256 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/__mocks__/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './services'; diff --git a/src/plugins/unified_doc_viewer/public/__mocks__/services.ts b/src/plugins/unified_doc_viewer/public/__mocks__/services.ts new file mode 100644 index 0000000000000..c43b8daa86727 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/__mocks__/services.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { analyticsServiceMock } from '@kbn/core-analytics-browser-mocks'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; +import type { UnifiedDocViewerServices, UnifiedDocViewerStart } from '../types'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; + +export const mockUnifiedDocViewer: jest.Mocked = { + getDocViews: jest.fn().mockReturnValue([]), +}; + +export const mockUnifiedDocViewerServices: jest.Mocked = { + analytics: analyticsServiceMock.createAnalyticsServiceStart(), + data: dataPluginMock.createStartContract(), + fieldFormats: fieldFormatsMock, + storage: new Storage(localStorage), + uiSettings: uiSettingsServiceMock.createStartContract(), + unifiedDocViewer: mockUnifiedDocViewer, +}; diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer/doc_viewer.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer/doc_viewer.tsx new file mode 100644 index 0000000000000..beb9a032d8c84 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer/doc_viewer.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import type { DocViewRenderProps } from '@kbn/unified-doc-viewer/types'; +import { DocViewer } from '@kbn/unified-doc-viewer'; +import { getUnifiedDocViewerServices } from '../../plugin'; + +export function UnifiedDocViewer(props: DocViewRenderProps) { + const services = getUnifiedDocViewerServices(); + return ( + + + + ); +} diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer/index.ts b/src/plugins/unified_doc_viewer/public/components/doc_viewer/index.ts new file mode 100644 index 0000000000000..799dfb8c9289f --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { UnifiedDocViewer } from './doc_viewer'; + +// Required for usage in React.lazy +// eslint-disable-next-line import/no-default-export +export default UnifiedDocViewer; diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.test.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.test.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.tsx similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.tsx diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/index.ts b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/index.ts similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_source/index.ts rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_source/index.ts diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.scss b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.scss similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.scss rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.scss diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.test.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.test.tsx similarity index 94% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.test.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.test.tsx index 03853ba6b8d9e..02f31a2e4f46c 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.test.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.test.tsx @@ -10,10 +10,10 @@ import React from 'react'; import type { DataView } from '@kbn/data-views-plugin/public'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { DocViewerSource } from './source'; -import * as hooks from '../../../../hooks/use_es_doc_search'; +import * as hooks from '../../hooks/use_es_doc_search'; import * as useUiSettingHook from '@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting'; import { EuiButton, EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui'; -import { JsonCodeEditorCommon } from '../../../../components/json_code_editor/json_code_editor_common'; +import { JsonCodeEditorCommon } from '../json_code_editor'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { buildDataTableRecord } from '@kbn/discover-utils'; import { of } from 'rxjs'; @@ -53,6 +53,7 @@ describe('Source Viewer component', () => { dataView={mockDataView} width={123} hasLineNumbers={true} + onRefresh={() => {}} /> ); @@ -71,6 +72,7 @@ describe('Source Viewer component', () => { dataView={mockDataView} width={123} hasLineNumbers={true} + onRefresh={() => {}} /> ); @@ -110,6 +112,7 @@ describe('Source Viewer component', () => { dataView={mockDataView} width={123} hasLineNumbers={true} + onRefresh={() => {}} /> ); diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx similarity index 77% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx index 95c3b8b34e5d9..26c771e405be8 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx @@ -12,14 +12,13 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { monaco } from '@kbn/monaco'; import { EuiButton, EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { DataView } from '@kbn/data-views-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; import type { DataTableRecord } from '@kbn/discover-utils/types'; +import { ElasticRequestState } from '@kbn/unified-doc-viewer'; import { DOC_TABLE_LEGACY, SEARCH_FIELDS_FROM_SOURCE } from '@kbn/discover-utils'; -import { useDiscoverServices } from '../../../../hooks/use_discover_services'; -import { JSONCodeEditorCommonMemoized } from '../../../../components/json_code_editor/json_code_editor_common'; -import { useEsDocSearch } from '../../../../hooks/use_es_doc_search'; -import { ElasticRequestState } from '../../../../application/doc/types'; +import { useEsDocSearch, useUnifiedDocViewerServices } from '../../hooks'; import { getHeight } from './get_height'; +import { JSONCodeEditorCommonMemoized } from '../json_code_editor'; interface SourceViewerProps { id: string; @@ -28,6 +27,8 @@ interface SourceViewerProps { textBasedHits?: DataTableRecord[]; hasLineNumbers: boolean; width?: number; + requestState?: ElasticRequestState; + onRefresh: () => void; } // Ihe number of lines displayed without scrolling used for classic table, which renders the component @@ -43,14 +44,15 @@ export const DocViewerSource = ({ width, hasLineNumbers, textBasedHits, + onRefresh, }: SourceViewerProps) => { const [editor, setEditor] = useState(); const [editorHeight, setEditorHeight] = useState(); const [jsonValue, setJsonValue] = useState(''); - const { uiSettings } = useDiscoverServices(); + const { uiSettings } = useUnifiedDocViewerServices(); const useNewFieldsApi = !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE); const useDocExplorer = !uiSettings.get(DOC_TABLE_LEGACY); - const [reqState, hit, requestData] = useEsDocSearch({ + const [requestState, hit] = useEsDocSearch({ id, index, dataView, @@ -59,10 +61,10 @@ export const DocViewerSource = ({ }); useEffect(() => { - if (reqState === ElasticRequestState.Found && hit) { + if (requestState === ElasticRequestState.Found && hit) { setJsonValue(JSON.stringify(hit.raw, undefined, 2)); } - }, [reqState, hit]); + }, [requestState, hit]); // setting editor height // - classic view: based on lines height and count to stretch and fit its content @@ -93,26 +95,26 @@ export const DocViewerSource = ({
    - +
    ); const errorMessageTitle = (

    - {i18n.translate('discover.sourceViewer.errorMessageTitle', { + {i18n.translate('unifiedDocViewer.sourceViewer.errorMessageTitle', { defaultMessage: 'An Error Occurred', })}

    ); const errorMessage = (
    - {i18n.translate('discover.sourceViewer.errorMessage', { + {i18n.translate('unifiedDocViewer.sourceViewer.errorMessage', { defaultMessage: 'Could not fetch data at this time. Refresh the tab to try again.', })} - - {i18n.translate('discover.sourceViewer.refresh', { + + {i18n.translate('unifiedDocViewer.sourceViewer.refresh', { defaultMessage: 'Refresh', })} @@ -122,11 +124,11 @@ export const DocViewerSource = ({ ); - if (reqState === ElasticRequestState.Error || reqState === ElasticRequestState.NotFound) { + if (requestState === ElasticRequestState.Error || requestState === ElasticRequestState.NotFound) { return errorState; } - if (reqState === ElasticRequestState.Loading || jsonValue === '') { + if (requestState === ElasticRequestState.Loading || jsonValue === '') { return loadingState; } diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/index.ts b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/index.ts similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/index.ts rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/index.ts diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/index.ts b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/index.ts similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/index.ts rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/index.ts diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.test.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.test.tsx similarity index 97% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.test.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.test.tsx index d1ab0d3d8b3e5..3a614ef71ad5e 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.test.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.test.tsx @@ -10,11 +10,11 @@ import React from 'react'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { findTestSubject } from '@elastic/eui/lib/test'; import { DocViewerLegacyTable } from './table'; -import { DataView } from '@kbn/data-views-plugin/public'; -import { DocViewRenderProps } from '../../../doc_views_types'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import type { DocViewRenderProps } from '@kbn/unified-doc-viewer/types'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { DiscoverServices } from '../../../../../build_services'; import { buildDataTableRecord } from '@kbn/discover-utils'; +import type { UnifiedDocViewerServices } from '../../../hooks'; const services = { uiSettings: { @@ -73,7 +73,10 @@ dataView.fields.getByName = (name: string) => { return dataView.fields.getAll().find((field) => field.name === name); }; -const mountComponent = (props: DocViewRenderProps, overrides?: Partial) => { +const mountComponent = ( + props: DocViewRenderProps, + overrides?: Partial +) => { return mountWithIntl( {' '} @@ -419,7 +422,7 @@ describe('DocViewTable at Discover Doc with Fields API', () => { } }, }, - } as unknown as DiscoverServices; + } as unknown as UnifiedDocViewerServices; const component = mountComponent(props, overridedServices); const categoryKeywordRow = findTestSubject(component, 'tableDocViewRow-category.keyword'); diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx similarity index 94% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx index 1d465978b17b1..6b2a70b868911 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx @@ -17,8 +17,8 @@ import { getShouldShowFieldHandler, isNestedFieldParent, } from '@kbn/discover-utils'; -import { useDiscoverServices } from '../../../../../hooks/use_discover_services'; -import { DocViewRenderProps, FieldRecordLegacy } from '../../../doc_views_types'; +import type { DocViewRenderProps, FieldRecordLegacy } from '@kbn/unified-doc-viewer/types'; +import { useUnifiedDocViewerServices } from '../../../hooks'; import { ACTIONS_COLUMN, MAIN_COLUMNS } from './table_columns'; export const DocViewerLegacyTable = ({ @@ -29,7 +29,7 @@ export const DocViewerLegacyTable = ({ onAddColumn, onRemoveColumn, }: DocViewRenderProps) => { - const { fieldFormats, uiSettings } = useDiscoverServices(); + const { fieldFormats, uiSettings } = useUnifiedDocViewerServices(); const showMultiFields = useMemo(() => uiSettings.get(SHOW_MULTIFIELDS), [uiSettings]); const mapping = useCallback((name: string) => dataView.fields.getByName(name), [dataView.fields]); diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_cell_actions.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx similarity index 93% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_cell_actions.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx index 3ce4b789bd1ff..4499a44190747 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_cell_actions.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx @@ -7,12 +7,12 @@ */ import React from 'react'; -import { DataViewField } from '@kbn/data-views-plugin/public'; +import type { DataViewField } from '@kbn/data-views-plugin/public'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import { DocViewTableRowBtnFilterRemove } from './table_row_btn_filter_remove'; import { DocViewTableRowBtnFilterExists } from './table_row_btn_filter_exists'; import { DocViewTableRowBtnToggleColumn } from './table_row_btn_toggle_column'; import { DocViewTableRowBtnFilterAdd } from './table_row_btn_filter_add'; -import { DocViewFilterFn } from '../../../doc_views_types'; interface TableActionsProps { field: string; diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_columns.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_columns.tsx similarity index 84% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_columns.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_columns.tsx index 121187761b2c6..4b79a84970698 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_columns.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_columns.tsx @@ -9,10 +9,10 @@ import { EuiBasicTableColumn, EuiText } from '@elastic/eui'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { FieldName } from '../../../../../components/field_name/field_name'; +import type { FieldRecordLegacy } from '@kbn/unified-doc-viewer/types'; +import { FieldName } from '@kbn/unified-doc-viewer'; import { TableActions } from './table_cell_actions'; import { TableFieldValue } from '../table_cell_value'; -import { FieldRecordLegacy } from '../../../doc_views_types'; export const ACTIONS_COLUMN: EuiBasicTableColumn = { field: 'action', @@ -23,7 +23,7 @@ export const ACTIONS_COLUMN: EuiBasicTableColumn = { @@ -55,7 +55,10 @@ export const MAIN_COLUMNS: Array> = [ name: ( - + ), @@ -85,7 +88,10 @@ export const MAIN_COLUMNS: Array> = [ name: ( - + ), diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_row_btn_filter_add.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_row_btn_filter_add.tsx similarity index 77% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_row_btn_filter_add.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_row_btn_filter_add.tsx index ac3768cb96ecd..180dae22cb25f 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_row_btn_filter_add.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_row_btn_filter_add.tsx @@ -19,12 +19,12 @@ export interface Props { export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props) { const tooltipContent = disabled ? ( ) : ( ); @@ -32,9 +32,12 @@ export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props return ( ) : ( ) ) : ( ); @@ -44,9 +44,12 @@ export function DocViewTableRowBtnFilterExists({ return ( ) : ( ); @@ -32,9 +32,12 @@ export function DocViewTableRowBtnFilterRemove({ onClick, disabled = false }: Pr return ( } > { const showActionsInsideTableCell = useIsWithinBreakpoints(['xl'], true); - const { storage, uiSettings, fieldFormats } = useDiscoverServices(); + const { fieldFormats, storage, uiSettings } = useUnifiedDocViewerServices(); const showMultiFields = uiSettings.get(SHOW_MULTIFIELDS); const currentDataViewId = dataView.id!; const isSingleDocView = !filter; @@ -129,7 +129,7 @@ export const DocViewerTable = ({ [flattened, dataView, showMultiFields] ); - const searchPlaceholder = i18n.translate('discover.docView.table.searchPlaceHolder', { + const searchPlaceholder = i18n.translate('unifiedDocViewer.docView.table.searchPlaceHolder', { defaultMessage: 'Search field names', }); @@ -283,7 +283,7 @@ export const DocViewerTable = ({ @@ -293,14 +293,20 @@ export const DocViewerTable = ({ - + , - + , @@ -401,7 +407,10 @@ export const DocViewerTable = ({ {rowElements.length === 0 ? (

    - +

    ) : ( diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx similarity index 75% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx index 9f29f3ba7f69f..8b9a35e071310 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx @@ -17,7 +17,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { DataViewField } from '@kbn/data-views-plugin/public'; -import { DocViewFilterFn } from '../../doc_views_types'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; interface TableActionsProps { mode?: 'inline' | 'as_popover'; @@ -43,43 +43,49 @@ export const TableActions = ({ onTogglePinned, }: TableActionsProps) => { const [isOpen, setIsOpen] = useState(false); - const openActionsLabel = i18n.translate('discover.docView.table.actions.open', { + const openActionsLabel = i18n.translate('unifiedDocViewer.docView.table.actions.open', { defaultMessage: 'Open actions', }); - const actionsLabel = i18n.translate('discover.docView.table.actions.label', { + const actionsLabel = i18n.translate('unifiedDocViewer.docView.table.actions.label', { defaultMessage: 'Actions', }); // Filters pair const filtersPairDisabled = !fieldMapping || !fieldMapping.filterable || ignoredValue; - const filterAddLabel = i18n.translate('discover.docViews.table.filterForValueButtonTooltip', { - defaultMessage: 'Filter for value', - }); + const filterAddLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.filterForValueButtonTooltip', + { + defaultMessage: 'Filter for value', + } + ); const filterAddAriaLabel = i18n.translate( - 'discover.docViews.table.filterForValueButtonAriaLabel', + 'unifiedDocViewer.docViews.table.filterForValueButtonAriaLabel', { defaultMessage: 'Filter for value' } ); - const filterOutLabel = i18n.translate('discover.docViews.table.filterOutValueButtonTooltip', { - defaultMessage: 'Filter out value', - }); + const filterOutLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.filterOutValueButtonTooltip', + { + defaultMessage: 'Filter out value', + } + ); const filterOutAriaLabel = i18n.translate( - 'discover.docViews.table.filterOutValueButtonAriaLabel', + 'unifiedDocViewer.docViews.table.filterOutValueButtonAriaLabel', { defaultMessage: 'Filter out value' } ); const filtersPairToolTip = (filtersPairDisabled && - i18n.translate('discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip', { + i18n.translate('unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip', { defaultMessage: 'Unindexed fields or ignored values cannot be searched', })) || undefined; // Filter exists const filterExistsLabel = i18n.translate( - 'discover.docViews.table.filterForFieldPresentButtonTooltip', + 'unifiedDocViewer.docViews.table.filterForFieldPresentButtonTooltip', { defaultMessage: 'Filter for field present' } ); const filterExistsAriaLabel = i18n.translate( - 'discover.docViews.table.filterForFieldPresentButtonAriaLabel', + 'unifiedDocViewer.docViews.table.filterForFieldPresentButtonAriaLabel', { defaultMessage: 'Filter for field present' } ); const filtersExistsDisabled = !fieldMapping || !fieldMapping.filterable; @@ -87,35 +93,44 @@ export const TableActions = ({ (filtersExistsDisabled && (fieldMapping && fieldMapping.scripted ? i18n.translate( - 'discover.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip', + 'unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip', { defaultMessage: 'Unable to filter for presence of scripted fields', } ) - : i18n.translate('discover.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip', { - defaultMessage: 'Unable to filter for presence of meta fields', - }))) || + : i18n.translate( + 'unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip', + { + defaultMessage: 'Unable to filter for presence of meta fields', + } + ))) || undefined; // Toggle columns const toggleColumnsLabel = i18n.translate( - 'discover.docViews.table.toggleColumnInTableButtonTooltip', + 'unifiedDocViewer.docViews.table.toggleColumnInTableButtonTooltip', { defaultMessage: 'Toggle column in table' } ); const toggleColumnsAriaLabel = i18n.translate( - 'discover.docViews.table.toggleColumnInTableButtonAriaLabel', + 'unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel', { defaultMessage: 'Toggle column in table' } ); // Pinned const pinnedLabel = pinned - ? i18n.translate('discover.docViews.table.unpinFieldLabel', { defaultMessage: 'Unpin field' }) - : i18n.translate('discover.docViews.table.pinFieldLabel', { defaultMessage: 'Pin field' }); + ? i18n.translate('unifiedDocViewer.docViews.table.unpinFieldLabel', { + defaultMessage: 'Unpin field', + }) + : i18n.translate('unifiedDocViewer.docViews.table.pinFieldLabel', { + defaultMessage: 'Pin field', + }); const pinnedAriaLabel = pinned - ? i18n.translate('discover.docViews.table.unpinFieldAriaLabel', { + ? i18n.translate('unifiedDocViewer.docViews.table.unpinFieldAriaLabel', { defaultMessage: 'Unpin field', }) - : i18n.translate('discover.docViews.table.pinFieldAriaLabel', { defaultMessage: 'Pin field' }); + : i18n.translate('unifiedDocViewer.docViews.table.pinFieldAriaLabel', { + defaultMessage: 'Pin field', + }); const pinnedIconType = pinned ? 'pinFilled' : 'pin'; const toggleOpenPopover = useCallback(() => setIsOpen((current) => !current), []); diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_value.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx similarity index 83% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_value.tsx rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx index d1ec9d369439f..79c79e6a45836 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_value.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx @@ -26,26 +26,26 @@ const IgnoreWarning: React.FC = React.memo(({ rawValue, reas switch (reason) { case IgnoredReason.IGNORE_ABOVE: return multiValue - ? i18n.translate('discover.docView.table.ignored.multiAboveTooltip', { + ? i18n.translate('unifiedDocViewer.docView.table.ignored.multiAboveTooltip', { defaultMessage: `One or more values in this field are too long and can't be searched or filtered.`, }) - : i18n.translate('discover.docView.table.ignored.singleAboveTooltip', { + : i18n.translate('unifiedDocViewer.docView.table.ignored.singleAboveTooltip', { defaultMessage: `The value in this field is too long and can't be searched or filtered.`, }); case IgnoredReason.MALFORMED: return multiValue - ? i18n.translate('discover.docView.table.ignored.multiMalformedTooltip', { + ? i18n.translate('unifiedDocViewer.docView.table.ignored.multiMalformedTooltip', { defaultMessage: `This field has one or more malformed values that can't be searched or filtered.`, }) - : i18n.translate('discover.docView.table.ignored.singleMalformedTooltip', { + : i18n.translate('unifiedDocViewer.docView.table.ignored.singleMalformedTooltip', { defaultMessage: `The value in this field is malformed and can't be searched or filtered.`, }); case IgnoredReason.UNKNOWN: return multiValue - ? i18n.translate('discover.docView.table.ignored.multiUnknownTooltip', { + ? i18n.translate('unifiedDocViewer.docView.table.ignored.multiUnknownTooltip', { defaultMessage: `One or more values in this field were ignored by Elasticsearch and can't be searched or filtered.`, }) - : i18n.translate('discover.docView.table.ignored.singleUnknownTooltip', { + : i18n.translate('unifiedDocViewer.docView.table.ignored.singleUnknownTooltip', { defaultMessage: `The value in this field was ignored by Elasticsearch and can't be searched or filtered.`, }); } @@ -67,10 +67,10 @@ const IgnoreWarning: React.FC = React.memo(({ rawValue, reas {multiValue - ? i18n.translate('discover.docViews.table.ignored.multiValueLabel', { + ? i18n.translate('unifiedDocViewer.docViews.table.ignored.multiValueLabel', { defaultMessage: 'Contains ignored values', }) - : i18n.translate('discover.docViews.table.ignored.singleValueLabel', { + : i18n.translate('unifiedDocViewer.docViews.table.ignored.singleValueLabel', { defaultMessage: 'Ignored value', })} diff --git a/src/plugins/unified_doc_viewer/public/components/index.ts b/src/plugins/unified_doc_viewer/public/components/index.ts new file mode 100644 index 0000000000000..b5f3a8948d689 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './doc_viewer'; +export * from './doc_viewer_source'; +export * from './doc_viewer_table'; +export * from './json_code_editor'; diff --git a/src/plugins/unified_doc_viewer/public/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap b/src/plugins/unified_doc_viewer/public/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap new file mode 100644 index 0000000000000..7af546298e0d8 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`returns the \`JsonCodeEditor\` component 1`] = ` + +`; diff --git a/src/plugins/unified_doc_viewer/public/components/json_code_editor/index.ts b/src/plugins/unified_doc_viewer/public/components/json_code_editor/index.ts new file mode 100644 index 0000000000000..d0e3147e65ab1 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/json_code_editor/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 * from './json_code_editor'; +export * from './json_code_editor_common'; diff --git a/src/plugins/discover/public/components/json_code_editor/json_code_editor.scss b/src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor.scss similarity index 100% rename from src/plugins/discover/public/components/json_code_editor/json_code_editor.scss rename to src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor.scss diff --git a/src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor.test.tsx b/src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor.test.tsx new file mode 100644 index 0000000000000..e1ec1373f8657 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor.test.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 JsonCodeEditor from './json_code_editor'; + +it('returns the `JsonCodeEditor` component', () => { + const value = { + _index: 'test', + _type: 'doc', + _id: 'foo', + _score: 1, + _source: { test: 123 }, + }; + expect(shallow()).toMatchSnapshot(); +}); diff --git a/src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor.tsx b/src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor.tsx new file mode 100644 index 0000000000000..d08e35eb6d4bf --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor.tsx @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 './json_code_editor.scss'; + +import React from 'react'; +import { JsonCodeEditorCommon } from './json_code_editor_common'; + +export interface JsonCodeEditorProps { + json: Record; + width?: string | number; + height?: string | number; + hasLineNumbers?: boolean; +} + +// Required for usage in React.lazy +// eslint-disable-next-line import/no-default-export +export default function JsonCodeEditor({ + json, + width, + height, + hasLineNumbers, +}: JsonCodeEditorProps) { + const jsonValue = JSON.stringify(json, null, 2); + + return ( + void 0} + hideCopyButton={true} + /> + ); +} diff --git a/src/plugins/discover/public/components/json_code_editor/json_code_editor_common.tsx b/src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor_common.tsx similarity index 93% rename from src/plugins/discover/public/components/json_code_editor/json_code_editor_common.tsx rename to src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor_common.tsx index 777240fe2f5bb..fa5dbfbe616ea 100644 --- a/src/plugins/discover/public/components/json_code_editor/json_code_editor_common.tsx +++ b/src/plugins/unified_doc_viewer/public/components/json_code_editor/json_code_editor_common.tsx @@ -14,10 +14,10 @@ import { monaco, XJsonLang } from '@kbn/monaco'; import { EuiButtonEmpty, EuiCopy, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { CodeEditor } from '@kbn/kibana-react-plugin/public'; -const codeEditorAriaLabel = i18n.translate('discover.json.codeEditorAriaLabel', { +const codeEditorAriaLabel = i18n.translate('unifiedDocViewer.json.codeEditorAriaLabel', { defaultMessage: 'Read only JSON view of an elasticsearch document', }); -const copyToClipboardLabel = i18n.translate('discover.json.copyToClipboardLabel', { +const copyToClipboardLabel = i18n.translate('unifiedDocViewer.json.copyToClipboardLabel', { defaultMessage: 'Copy to clipboard', }); diff --git a/src/plugins/unified_doc_viewer/public/hooks/index.ts b/src/plugins/unified_doc_viewer/public/hooks/index.ts new file mode 100644 index 0000000000000..547032ce4415e --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/hooks/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 * from './use_doc_viewer_services'; +export * from './use_es_doc_search'; diff --git a/src/plugins/unified_doc_viewer/public/hooks/use_doc_viewer_services.ts b/src/plugins/unified_doc_viewer/public/hooks/use_doc_viewer_services.ts new file mode 100644 index 0000000000000..4287e87ea6aa3 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/hooks/use_doc_viewer_services.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { AnalyticsServiceStart } from '@kbn/core-analytics-browser'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import type { Storage } from '@kbn/kibana-utils-plugin/public'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import type { UnifiedDocViewerStart } from '../plugin'; + +export interface UnifiedDocViewerServices { + analytics: AnalyticsServiceStart; + data: DataPublicPluginStart; + fieldFormats: FieldFormatsStart; + storage: Storage; + uiSettings: IUiSettingsClient; + unifiedDocViewer: UnifiedDocViewerStart; +} + +export function useUnifiedDocViewerServices(): UnifiedDocViewerServices { + const { services } = useKibana(); + const { analytics, data, fieldFormats, storage, uiSettings, unifiedDocViewer } = services; + return { analytics, data, fieldFormats, storage, uiSettings, unifiedDocViewer }; +} diff --git a/src/plugins/discover/public/hooks/use_es_doc_search.test.tsx b/src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.test.tsx similarity index 93% rename from src/plugins/discover/public/hooks/use_es_doc_search.test.tsx rename to src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.test.tsx index 64a998a542069..cee1cf509e138 100644 --- a/src/plugins/discover/public/hooks/use_es_doc_search.test.tsx +++ b/src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.test.tsx @@ -7,11 +7,10 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; -import { buildSearchBody, useEsDocSearch } from './use_es_doc_search'; +import { type EsDocSearchProps, buildSearchBody, useEsDocSearch } from './use_es_doc_search'; import { Subject } from 'rxjs'; -import { DataView } from '@kbn/data-views-plugin/public'; -import { DocProps } from '../application/doc/components/doc'; -import { ElasticRequestState } from '../application/doc/types'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import { ElasticRequestState } from '@kbn/unified-doc-viewer'; import { SEARCH_FIELDS_FROM_SOURCE as mockSearchFieldsFromSource, buildDataTableRecord, @@ -227,9 +226,9 @@ describe('Test of helper / hook', () => { id: '1', index: 'index1', dataView, - } as unknown as DocProps; + } as unknown as EsDocSearchProps; - const hook = renderHook((p: DocProps) => useEsDocSearch(p), { + const hook = renderHook((p: EsDocSearchProps) => useEsDocSearch(p), { initialProps: props, wrapper: ({ children }) => ( {children} @@ -251,9 +250,9 @@ describe('Test of helper / hook', () => { id: '1', index: 'index1', dataView, - } as unknown as DocProps; + } as unknown as EsDocSearchProps; - const hook = renderHook((p: DocProps) => useEsDocSearch(p), { + const hook = renderHook((p: EsDocSearchProps) => useEsDocSearch(p), { initialProps: props, wrapper: ({ children }) => ( {children} @@ -305,9 +304,9 @@ describe('Test of helper / hook', () => { flattened: { field1: 1, field2: 2 }, }, ], - } as unknown as DocProps; + } as unknown as EsDocSearchProps; - const hook = renderHook((p: DocProps) => useEsDocSearch(p), { + const hook = renderHook((p: EsDocSearchProps) => useEsDocSearch(p), { initialProps: props, wrapper: ({ children }) => ( {children} diff --git a/src/plugins/discover/public/hooks/use_es_doc_search.ts b/src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.ts similarity index 84% rename from src/plugins/discover/public/hooks/use_es_doc_search.ts rename to src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.ts index b430d6b4531b9..d215306d6f7ea 100644 --- a/src/plugins/discover/public/hooks/use_es_doc_search.ts +++ b/src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.ts @@ -9,16 +9,38 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { lastValueFrom } from 'rxjs'; -import { DataView } from '@kbn/data-views-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; import { reportPerformanceMetricEvent } from '@kbn/ebt-tools'; import type { DataTableRecord } from '@kbn/discover-utils/types'; import { SEARCH_FIELDS_FROM_SOURCE, buildDataTableRecord } from '@kbn/discover-utils'; -import { DocProps } from '../application/doc/components/doc'; -import { ElasticRequestState } from '../application/doc/types'; -import { useDiscoverServices } from './use_discover_services'; +import { ElasticRequestState } from '@kbn/unified-doc-viewer'; +import { useUnifiedDocViewerServices } from './use_doc_viewer_services'; type RequestBody = Pick; +export interface EsDocSearchProps { + /** + * Id of the doc in ES + */ + id: string; + /** + * Index in ES to query + */ + index: string; + /** + * DataView entity + */ + dataView: DataView; + /** + * If set, will always request source, regardless of the global `fieldsFromSource` setting + */ + requestSource?: boolean; + /** + * Records fetched from text based query + */ + textBasedHits?: DataTableRecord[]; +} + /** * Custom react hook for querying a single doc in ElasticSearch */ @@ -28,10 +50,10 @@ export function useEsDocSearch({ dataView, requestSource, textBasedHits, -}: DocProps): [ElasticRequestState, DataTableRecord | null, () => void] { +}: EsDocSearchProps): [ElasticRequestState, DataTableRecord | null, () => void] { const [status, setStatus] = useState(ElasticRequestState.Loading); const [hit, setHit] = useState(null); - const { data, uiSettings, analytics } = useDiscoverServices(); + const { data, uiSettings, analytics } = useUnifiedDocViewerServices(); const useNewFieldsApi = useMemo(() => !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), [uiSettings]); const requestData = useCallback(async () => { diff --git a/src/plugins/unified_doc_viewer/public/index.tsx b/src/plugins/unified_doc_viewer/public/index.tsx new file mode 100644 index 0000000000000..d08de9dcaa0eb --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/index.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { withSuspense } from '@kbn/shared-ux-utility'; +import { EuiDelayRender, EuiSkeletonText } from '@elastic/eui'; +import { DocViewRenderProps } from '@kbn/unified-doc-viewer/src/services/types'; +import type { JsonCodeEditorProps } from './components'; +import { UnifiedDocViewerPublicPlugin } from './plugin'; + +export type { UnifiedDocViewerSetup, UnifiedDocViewerStart } from './plugin'; + +const LazyJsonCodeEditor = React.lazy( + () => import('./components/json_code_editor/json_code_editor') +); + +export const JsonCodeEditor = withSuspense( + LazyJsonCodeEditor, + + + +); + +const LazyUnifiedDocViewer = React.lazy(() => import('./components/doc_viewer')); +export const UnifiedDocViewer = withSuspense( + LazyUnifiedDocViewer, + + + +); + +export { useEsDocSearch, useUnifiedDocViewerServices } from './hooks'; + +export const plugin = () => new UnifiedDocViewerPublicPlugin(); diff --git a/src/plugins/unified_doc_viewer/public/plugin.tsx b/src/plugins/unified_doc_viewer/public/plugin.tsx new file mode 100644 index 0000000000000..018e6ffadd312 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/plugin.tsx @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import type { CoreSetup, Plugin } from '@kbn/core/public'; +import { DOC_TABLE_LEGACY } from '@kbn/discover-utils'; +import { i18n } from '@kbn/i18n'; +import { DocViewsRegistry } from '@kbn/unified-doc-viewer'; +import { EuiDelayRender, EuiSkeletonText } from '@elastic/eui'; +import { createGetterSetter, Storage } from '@kbn/kibana-utils-plugin/public'; +import { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import { CoreStart } from '@kbn/core/public'; +import { type UnifiedDocViewerServices, useUnifiedDocViewerServices } from './hooks'; + +export const [getUnifiedDocViewerServices, setUnifiedDocViewerServices] = + createGetterSetter('UnifiedDocViewerServices'); + +const DocViewerLegacyTable = React.lazy(() => import('./components/doc_viewer_table/legacy')); +const DocViewerTable = React.lazy(() => import('./components/doc_viewer_table')); +const SourceViewer = React.lazy(() => import('./components/doc_viewer_source')); + +export interface UnifiedDocViewerSetup { + addDocView: DocViewsRegistry['addDocView']; +} + +export interface UnifiedDocViewerStart { + getDocViews: DocViewsRegistry['getDocViewsSorted']; +} + +export interface UnifiedDocViewerStartDeps { + data: DataPublicPluginStart; + fieldFormats: FieldFormatsStart; +} + +export class UnifiedDocViewerPublicPlugin + implements Plugin +{ + private docViewsRegistry = new DocViewsRegistry(); + + public setup(core: CoreSetup) { + this.docViewsRegistry.addDocView({ + title: i18n.translate('unifiedDocViewer.docViews.table.tableTitle', { + defaultMessage: 'Table', + }), + order: 10, + component: (props) => { + // eslint-disable-next-line react-hooks/rules-of-hooks + const { uiSettings } = useUnifiedDocViewerServices(); + const DocView = uiSettings.get(DOC_TABLE_LEGACY) ? DocViewerLegacyTable : DocViewerTable; + + return ( + + + + } + > + + + ); + }, + }); + + this.docViewsRegistry.addDocView({ + title: i18n.translate('unifiedDocViewer.docViews.json.jsonTitle', { + defaultMessage: 'JSON', + }), + order: 20, + component: ({ hit, dataView, query, textBasedHits }) => { + return ( + + + + } + > + {}} + /> + + ); + }, + }); + + return { + addDocView: this.docViewsRegistry.addDocView.bind(this.docViewsRegistry), + }; + } + + public start(core: CoreStart, deps: UnifiedDocViewerStartDeps) { + const { analytics, uiSettings } = core; + const { data, fieldFormats } = deps; + const storage = new Storage(localStorage); + const unifiedDocViewer = { + getDocViews: this.docViewsRegistry.getDocViewsSorted.bind(this.docViewsRegistry), + }; + const services = { analytics, data, fieldFormats, storage, uiSettings, unifiedDocViewer }; + setUnifiedDocViewerServices(services); + return unifiedDocViewer; + } +} diff --git a/src/plugins/unified_doc_viewer/public/types.ts b/src/plugins/unified_doc_viewer/public/types.ts new file mode 100644 index 0000000000000..d9ec40eedfffb --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/types.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { JsonCodeEditorProps } from './components'; +export type { EsDocSearchProps, UnifiedDocViewerServices } from './hooks'; +export type { UnifiedDocViewerSetup, UnifiedDocViewerStart } from './plugin'; diff --git a/src/plugins/unified_doc_viewer/tsconfig.json b/src/plugins/unified_doc_viewer/tsconfig.json new file mode 100644 index 0000000000000..3e959ca047e40 --- /dev/null +++ b/src/plugins/unified_doc_viewer/tsconfig.json @@ -0,0 +1,31 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + }, + "include": [ "../../../typings/**/*", "common/**/*", "public/**/*", "server/**/*"], + "kbn_references": [ + "@kbn/kibana-react-plugin", + "@kbn/monaco", + "@kbn/data-views-plugin", + "@kbn/test-jest-helpers", + "@kbn/discover-utils", + "@kbn/i18n-react", + "@kbn/i18n", + "@kbn/unified-doc-viewer", + "@kbn/unified-field-list", + "@kbn/kibana-utils-plugin", + "@kbn/data-plugin", + "@kbn/core-analytics-browser", + "@kbn/field-formats-plugin", + "@kbn/core-ui-settings-browser", + "@kbn/ebt-tools", + "@kbn/core", + "@kbn/shared-ux-utility", + "@kbn/core-analytics-browser-mocks", + "@kbn/core-ui-settings-browser-mocks" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/src/plugins/unified_histogram/public/__mocks__/suggestions.ts b/src/plugins/unified_histogram/public/__mocks__/suggestions.ts index 0a92393f60ec3..bed2eee388cde 100644 --- a/src/plugins/unified_histogram/public/__mocks__/suggestions.ts +++ b/src/plugins/unified_histogram/public/__mocks__/suggestions.ts @@ -39,7 +39,7 @@ export const currentSuggestionMock = { '46aa21fa-b747-4543-bf90-0b40007c546d': { index: 'd3d7af60-4c81-11e8-b3d7-01146121b73d', query: { - sql: 'SELECT Dest, AvgTicketPrice FROM "kibana_sample_data_flights"', + esql: 'FROM kibana_sample_data_flights | keep Dest, AvgTicketPrice', }, columns: [ { @@ -141,7 +141,7 @@ export const currentSuggestionMock = { fieldName: '', contextualFields: ['Dest', 'AvgTicketPrice'], query: { - sql: 'SELECT Dest, AvgTicketPrice FROM "kibana_sample_data_flights"', + esql: 'FROM "kibana_sample_data_flights"', }, }, }, @@ -178,7 +178,7 @@ export const allSuggestionsMock = [ '2513a3d4-ad9d-48ea-bd58-8b6419ab97e6': { index: 'd3d7af60-4c81-11e8-b3d7-01146121b73d', query: { - sql: 'SELECT Dest, AvgTicketPrice FROM "kibana_sample_data_flights"', + esql: 'FROM "kibana_sample_data_flights"', }, columns: [ { @@ -281,7 +281,7 @@ export const allSuggestionsMock = [ fieldName: '', contextualFields: ['Dest', 'AvgTicketPrice'], query: { - sql: 'SELECT Dest, AvgTicketPrice FROM "kibana_sample_data_flights"', + esql: 'FROM "kibana_sample_data_flights"', }, }, }, diff --git a/src/plugins/unified_histogram/public/chart/chart.test.tsx b/src/plugins/unified_histogram/public/chart/chart.test.tsx index 640ca91c0bc89..3ce4f829ebac3 100644 --- a/src/plugins/unified_histogram/public/chart/chart.test.tsx +++ b/src/plugins/unified_histogram/public/chart/chart.test.tsx @@ -103,6 +103,7 @@ async function mountComponent({ onResetChartHeight: jest.fn(), onChartHiddenChange: jest.fn(), onTimeIntervalChange: jest.fn(), + withDefaultActions: undefined, }; let instance: ReactWrapper = {} as ReactWrapper; diff --git a/src/plugins/unified_histogram/public/chart/chart.tsx b/src/plugins/unified_histogram/public/chart/chart.tsx index ba6ffbaf149fe..0172b1b6107c1 100644 --- a/src/plugins/unified_histogram/public/chart/chart.tsx +++ b/src/plugins/unified_histogram/public/chart/chart.tsx @@ -16,7 +16,7 @@ import { EuiToolTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { Suggestion } from '@kbn/lens-plugin/public'; +import type { EmbeddableComponentProps, Suggestion } from '@kbn/lens-plugin/public'; import type { Datatable } from '@kbn/expressions-plugin/common'; import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/public'; import type { LensEmbeddableInput } from '@kbn/lens-plugin/public'; @@ -69,6 +69,7 @@ export interface ChartProps { disabledActions?: LensEmbeddableInput['disabledActions']; input$?: UnifiedHistogramInput$; lensTablesAdapter?: Record; + isOnHistogramMode?: boolean; onResetChartHeight?: () => void; onChartHiddenChange?: (chartHidden: boolean) => void; onTimeIntervalChange?: (timeInterval: string) => void; @@ -78,6 +79,7 @@ export interface ChartProps { onChartLoad?: (event: UnifiedHistogramChartLoadEvent) => void; onFilter?: LensEmbeddableInput['onFilter']; onBrushEnd?: LensEmbeddableInput['onBrushEnd']; + withDefaultActions: EmbeddableComponentProps['withDefaultActions']; } const HistogramMemoized = memo(Histogram); @@ -104,6 +106,7 @@ export function Chart({ disabledActions, input$: originalInput$, lensTablesAdapter, + isOnHistogramMode, onResetChartHeight, onChartHiddenChange, onTimeIntervalChange, @@ -113,6 +116,7 @@ export function Chart({ onChartLoad, onFilter, onBrushEnd, + withDefaultActions, }: ChartProps) { const [isSaveModalVisible, setIsSaveModalVisible] = useState(false); const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); @@ -425,10 +429,11 @@ export function Chart({ disableTriggers={disableTriggers} disabledActions={disabledActions} onTotalHitsChange={onTotalHitsChange} - hasLensSuggestions={Boolean(currentSuggestion)} + hasLensSuggestions={!Boolean(isOnHistogramMode)} onChartLoad={onChartLoad} onFilter={onFilter} onBrushEnd={onBrushEnd} + withDefaultActions={withDefaultActions} /> {appendHistogram} diff --git a/src/plugins/unified_histogram/public/chart/chart_config_panel.test.tsx b/src/plugins/unified_histogram/public/chart/chart_config_panel.test.tsx index 710666ac6637b..ef673826672ea 100644 --- a/src/plugins/unified_histogram/public/chart/chart_config_panel.test.tsx +++ b/src/plugins/unified_histogram/public/chart/chart_config_panel.test.tsx @@ -36,7 +36,7 @@ describe('ChartConfigPanel', () => { isPlainRecord: true, lensTablesAdapter: lensTablesAdapterMock, query: { - sql: 'Select * from test', + esql: 'from test', }, }} /> diff --git a/src/plugins/unified_histogram/public/chart/histogram.test.tsx b/src/plugins/unified_histogram/public/chart/histogram.test.tsx index 4c651f0b5e391..78f06687a0e7e 100644 --- a/src/plugins/unified_histogram/public/chart/histogram.test.tsx +++ b/src/plugins/unified_histogram/public/chart/histogram.test.tsx @@ -38,7 +38,7 @@ const getMockLensAttributes = () => suggestion: undefined, }); -function mountComponent() { +function mountComponent(isPlainRecord = false, hasLensSuggestions = false) { const services = unifiedHistogramServicesMock; services.data.query.timefilter.timefilter.getAbsoluteTime = () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; @@ -51,7 +51,8 @@ function mountComponent() { request: { searchSessionId: '123', }, - hasLensSuggestions: false, + hasLensSuggestions, + isPlainRecord, hits: { status: UnifiedHistogramFetchStatus.loading, total: undefined, @@ -70,6 +71,7 @@ function mountComponent() { lensAttributesContext: getMockLensAttributes(), onTotalHitsChange: jest.fn(), onChartLoad: jest.fn(), + withDefaultActions: undefined, }; return { @@ -95,16 +97,18 @@ describe('Histogram', () => { attributes: getMockLensAttributes().attributes, onLoad: lensProps.onLoad, }); - expect(lensProps).toEqual(originalProps); + expect(lensProps).toMatchObject(expect.objectContaining(originalProps)); component.setProps({ request: { ...props.request, searchSessionId: '321' } }).update(); lensProps = component.find(embeddable).props(); - expect(lensProps).toEqual(originalProps); + expect(lensProps).toMatchObject(expect.objectContaining(originalProps)); await act(async () => { props.refetch$.next({ type: 'refetch' }); }); component.update(); lensProps = component.find(embeddable).props(); - expect(lensProps).toEqual({ ...originalProps, searchSessionId: '321' }); + expect(lensProps).toMatchObject( + expect.objectContaining({ ...originalProps, searchSessionId: '321' }) + ); }); it('should execute onLoad correctly', async () => { @@ -234,4 +238,76 @@ describe('Histogram', () => { ); expect(props.onChartLoad).toHaveBeenLastCalledWith({ adapters }); }); + + it('should execute onLoad correctly for textbased language and no Lens suggestions', async () => { + const { component, props } = mountComponent(true, false); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + const adapters = createDefaultInspectorAdapters(); + adapters.tables.tables.layerId = { + meta: { type: 'es_ql' }, + columns: [ + { + id: 'rows', + name: 'rows', + meta: { + type: 'number', + dimensionName: 'Vertical axis', + }, + }, + ], + rows: [ + { + rows: 16, + }, + { + rows: 4, + }, + ], + } as any; + act(() => { + onLoad(false, adapters); + }); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.complete, + 20 + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ adapters }); + }); + + it('should execute onLoad correctly for textbased language and Lens suggestions', async () => { + const { component, props } = mountComponent(true, true); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + const adapters = createDefaultInspectorAdapters(); + adapters.tables.tables.layerId = { + meta: { type: 'es_ql' }, + columns: [ + { + id: 'rows', + name: 'rows', + meta: { + type: 'number', + dimensionName: 'Vertical axis', + }, + }, + ], + rows: [ + { + var0: 5584.925311203319, + }, + { + var0: 6788.7777444444, + }, + ], + } as any; + act(() => { + onLoad(false, adapters); + }); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.complete, + 2 + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ adapters }); + }); }); diff --git a/src/plugins/unified_histogram/public/chart/histogram.tsx b/src/plugins/unified_histogram/public/chart/histogram.tsx index 761e701e8f9a6..0046e0b6a87bd 100644 --- a/src/plugins/unified_histogram/public/chart/histogram.tsx +++ b/src/plugins/unified_histogram/public/chart/histogram.tsx @@ -10,11 +10,11 @@ import { useEuiTheme, useResizeObserver } from '@elastic/eui'; import { css } from '@emotion/react'; import React, { useState, useRef, useEffect } from 'react'; import type { DataView } from '@kbn/data-views-plugin/public'; -import type { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; +import type { DefaultInspectorAdapters, Datatable } from '@kbn/expressions-plugin/common'; import type { IKibanaSearchResponse } from '@kbn/data-plugin/public'; import type { estypes } from '@elastic/elasticsearch'; import type { TimeRange } from '@kbn/es-query'; -import type { LensEmbeddableInput } from '@kbn/lens-plugin/public'; +import type { EmbeddableComponentProps, LensEmbeddableInput } from '@kbn/lens-plugin/public'; import { RequestStatus } from '@kbn/inspector-plugin/public'; import type { Observable } from 'rxjs'; import { @@ -50,8 +50,32 @@ export interface HistogramProps { onChartLoad?: (event: UnifiedHistogramChartLoadEvent) => void; onFilter?: LensEmbeddableInput['onFilter']; onBrushEnd?: LensEmbeddableInput['onBrushEnd']; + withDefaultActions: EmbeddableComponentProps['withDefaultActions']; } +const computeTotalHits = ( + hasLensSuggestions: boolean, + adapterTables: + | { + [key: string]: Datatable; + } + | undefined, + isPlainRecord?: boolean +) => { + if (isPlainRecord && hasLensSuggestions) { + return Object.values(adapterTables ?? {})?.[0]?.rows?.length; + } else if (isPlainRecord && !hasLensSuggestions) { + // ES|QL histogram case + let rowsCount = 0; + Object.values(adapterTables ?? {})?.[0]?.rows.forEach((r) => { + rowsCount += r.rows; + }); + return rowsCount; + } else { + return adapterTables?.unifiedHistogram?.meta?.statistics?.totalCount; + } +}; + export function Histogram({ services: { data, lens, uiSettings }, dataView, @@ -69,6 +93,7 @@ export function Histogram({ onChartLoad, onFilter, onBrushEnd, + withDefaultActions, }: HistogramProps) { const [bucketInterval, setBucketInterval] = useState(); const [chartSize, setChartSize] = useState('100%'); @@ -111,10 +136,7 @@ export function Histogram({ } const adapterTables = adapters?.tables?.tables; - const totalHits = - isPlainRecord && hasLensSuggestions - ? Object.values(adapterTables ?? {})?.[0]?.rows?.length - : adapterTables?.unifiedHistogram?.meta?.statistics?.totalCount; + const totalHits = computeTotalHits(hasLensSuggestions, adapterTables, isPlainRecord); onTotalHitsChange?.( isLoading ? UnifiedHistogramFetchStatus.loading : UnifiedHistogramFetchStatus.complete, @@ -189,6 +211,7 @@ export function Histogram({ disabledActions={disabledActions} onFilter={onFilter} onBrushEnd={onBrushEnd} + withDefaultActions={withDefaultActions} />
    {timeRangeDisplay} diff --git a/src/plugins/unified_histogram/public/chart/hooks/use_total_hits.test.ts b/src/plugins/unified_histogram/public/chart/hooks/use_total_hits.test.ts index 187bf76751007..e6f3aeaa3a002 100644 --- a/src/plugins/unified_histogram/public/chart/hooks/use_total_hits.test.ts +++ b/src/plugins/unified_histogram/public/chart/hooks/use_total_hits.test.ts @@ -123,7 +123,7 @@ describe('useTotalHits', () => { ...getDeps(), isPlainRecord: true, onTotalHitsChange, - query: { sql: 'select * from test' }, + query: { esql: 'from test' }, }; renderHook(() => useTotalHits(deps)); expect(onTotalHitsChange).toBeCalledTimes(1); diff --git a/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.test.ts b/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.test.ts index f54b1b5b5c456..2a4523d152066 100644 --- a/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.test.ts +++ b/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.test.ts @@ -636,7 +636,7 @@ describe('getLensAttributes', () => { }, "fieldName": "", "query": Object { - "sql": "SELECT Dest, AvgTicketPrice FROM \\"kibana_sample_data_flights\\"", + "esql": "FROM \\"kibana_sample_data_flights\\"", }, }, "layers": Object { @@ -675,7 +675,7 @@ describe('getLensAttributes', () => { ], "index": "d3d7af60-4c81-11e8-b3d7-01146121b73d", "query": Object { - "sql": "SELECT Dest, AvgTicketPrice FROM \\"kibana_sample_data_flights\\"", + "esql": "FROM kibana_sample_data_flights | keep Dest, AvgTicketPrice", }, "timeField": "timestamp", }, diff --git a/src/plugins/unified_histogram/public/container/container.tsx b/src/plugins/unified_histogram/public/container/container.tsx index 0633e9d710966..311a380790dec 100644 --- a/src/plugins/unified_histogram/public/container/container.tsx +++ b/src/plugins/unified_histogram/public/container/container.tsx @@ -55,6 +55,10 @@ export type UnifiedHistogramContainerProps = { | 'resizeRef' | 'appendHitsCounter' | 'children' + | 'onBrushEnd' + | 'onFilter' + | 'withDefaultActions' + | 'disabledActions' >; /** diff --git a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts index c0eeb9448eee7..c9ab0d5220aed 100644 --- a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts +++ b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts @@ -136,13 +136,13 @@ describe('useStateProps', () => { `); }); - it('should return the correct props when an SQL query is used', () => { + it('should return the correct props when an ES|QL query is used', () => { const stateService = getStateService({ initialState }); const { result } = renderHook(() => useStateProps({ stateService, dataView: dataViewWithTimefieldMock, - query: { sql: 'SELECT * FROM index' }, + query: { esql: 'FROM index' }, requestAdapter: new RequestAdapter(), searchSessionId: '123', }) @@ -222,7 +222,7 @@ describe('useStateProps', () => { useStateProps({ stateService, dataView: dataViewWithTimefieldMock, - query: { sql: 'SELECT * FROM index' }, + query: { esql: 'FROM index' }, requestAdapter: new RequestAdapter(), searchSessionId: '123', }) diff --git a/src/plugins/unified_histogram/public/layout/hooks/compute_interval.test.ts b/src/plugins/unified_histogram/public/layout/hooks/compute_interval.test.ts new file mode 100644 index 0000000000000..04a94d172d1ac --- /dev/null +++ b/src/plugins/unified_histogram/public/layout/hooks/compute_interval.test.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { calculateBounds } from '@kbn/data-plugin/public'; +import { computeInterval } from './compute_interval'; + +describe('computeInterval', () => { + const dataMock = dataPluginMock.createStartContract(); + dataMock.query.timefilter.timefilter.getTime = () => { + return { from: '1991-03-29T08:04:00.694Z', to: '2021-03-29T07:04:00.695Z' }; + }; + dataMock.query.timefilter.timefilter.calculateBounds = (timeRange) => { + return calculateBounds(timeRange); + }; + + it('should return correct interval for 24 hours timerange', () => { + expect( + computeInterval( + { + from: '2023-08-15T10:00:00.000Z', + to: '2023-08-16T10:17:34.591Z', + }, + dataMock + ) + ).toEqual('30 minute'); + }); + + it('should return correct interval for 7 days timerange', () => { + expect( + computeInterval( + { + from: '2023-08-08T21:00:00.000Z', + to: '2023-08-16T10:18:56.569Z', + }, + dataMock + ) + ).toEqual('3 hour'); + }); + + it('should return correct interval for 1 month timerange', () => { + expect( + computeInterval( + { + from: '2023-07-16T21:00:00.000Z', + to: '2023-08-16T10:19:43.573Z', + }, + dataMock + ) + ).toEqual('12 hour'); + }); + + it('should return correct interval for 1 year timerange', () => { + expect( + computeInterval( + { + from: '2022-08-15T21:00:00.000Z', + to: '2023-08-16T10:21:18.589Z', + }, + dataMock + ) + ).toEqual('1 week'); + }); +}); diff --git a/src/plugins/unified_histogram/public/layout/hooks/compute_interval.ts b/src/plugins/unified_histogram/public/layout/hooks/compute_interval.ts new file mode 100644 index 0000000000000..bf6270e8255c7 --- /dev/null +++ b/src/plugins/unified_histogram/public/layout/hooks/compute_interval.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { TimeRange } from '@kbn/es-query'; + +// follows the same logic with vega auto_date function +// we could move to a package and reuse in the future +const barTarget = 50; // same as vega +const roundInterval = (interval: number) => { + { + switch (true) { + case interval <= 500: // <= 0.5s + return '100 millisecond'; + case interval <= 5000: // <= 5s + return '1 second'; + case interval <= 7500: // <= 7.5s + return '5 second'; + case interval <= 15000: // <= 15s + return '10 second'; + case interval <= 45000: // <= 45s + return '30 second'; + case interval <= 180000: // <= 3m + return '1 minute'; + case interval <= 450000: // <= 9m + return '5 minute'; + case interval <= 1200000: // <= 20m + return '10 minute'; + case interval <= 2700000: // <= 45m + return '30 minute'; + case interval <= 7200000: // <= 2h + return '1 hour'; + case interval <= 21600000: // <= 6h + return '3 hour'; + case interval <= 86400000: // <= 24h + return '12 hour'; + case interval <= 604800000: // <= 1w + return '24 hour'; + case interval <= 1814400000: // <= 3w + return '1 week'; + case interval < 3628800000: // < 2y + return '30 day'; + default: + return '1 year'; + } + } +}; + +export const computeInterval = (timeRange: TimeRange, data: DataPublicPluginStart): string => { + const bounds = data.query.timefilter.timefilter.calculateBounds(timeRange!); + const min = bounds.min!.valueOf(); + const max = bounds.max!.valueOf(); + const interval = (max - min) / barTarget; + return roundInterval(interval); +}; diff --git a/src/plugins/unified_histogram/public/layout/hooks/use_lens_suggestions.ts b/src/plugins/unified_histogram/public/layout/hooks/use_lens_suggestions.ts index e4936b9345a6d..b6d02753d140a 100644 --- a/src/plugins/unified_histogram/public/layout/hooks/use_lens_suggestions.ts +++ b/src/plugins/unified_histogram/public/layout/hooks/use_lens_suggestions.ts @@ -5,13 +5,21 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - import { DataView } from '@kbn/data-views-plugin/common'; -import { AggregateQuery, isOfAggregateQueryType, Query } from '@kbn/es-query'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import { + AggregateQuery, + isOfAggregateQueryType, + getAggregateQueryMode, + Query, + TimeRange, +} from '@kbn/es-query'; import type { DatatableColumn } from '@kbn/expressions-plugin/common'; import { LensSuggestionsApi, Suggestion } from '@kbn/lens-plugin/public'; import { isEqual } from 'lodash'; import { useEffect, useMemo, useRef, useState } from 'react'; +import { computeInterval } from './compute_interval'; +const TRANSFORMATIONAL_COMMANDS = ['stats', 'project', 'keep']; export const useLensSuggestions = ({ dataView, @@ -19,6 +27,8 @@ export const useLensSuggestions = ({ originalSuggestion, isPlainRecord, columns, + data, + timeRange, lensSuggestionsApi, onSuggestionChange, }: { @@ -27,6 +37,8 @@ export const useLensSuggestions = ({ originalSuggestion?: Suggestion; isPlainRecord?: boolean; columns?: DatatableColumn[]; + data: DataPublicPluginStart; + timeRange?: TimeRange; lensSuggestionsApi: LensSuggestionsApi; onSuggestionChange?: (suggestion: Suggestion | undefined) => void; }) => { @@ -50,6 +62,63 @@ export const useLensSuggestions = ({ const currentSuggestion = originalSuggestion ?? suggestions.firstSuggestion; const suggestionDeps = useRef(getSuggestionDeps({ dataView, query, columns })); + const histogramSuggestion = useMemo(() => { + if ( + !currentSuggestion && + dataView.isTimeBased() && + query && + isOfAggregateQueryType(query) && + getAggregateQueryMode(query) === 'esql' && + timeRange + ) { + let queryHasTransformationalCommands = false; + if ('esql' in query) { + TRANSFORMATIONAL_COMMANDS.forEach((command: string) => { + if (query.esql.toLowerCase().includes(command)) { + queryHasTransformationalCommands = true; + return; + } + }); + } + + if (queryHasTransformationalCommands) return undefined; + + const interval = computeInterval(timeRange, data); + const language = getAggregateQueryMode(query); + const histogramQuery = `${query[language]} | eval uniqueName = 1 + | EVAL timestamp=DATE_TRUNC(${interval}, ${dataView.timeFieldName}) | stats rows = count(uniqueName) by timestamp | rename timestamp as \`${dataView.timeFieldName} every ${interval}\``; + const context = { + dataViewSpec: dataView?.toSpec(), + fieldName: '', + textBasedColumns: [ + { + id: `${dataView.timeFieldName} every ${interval}`, + name: `${dataView.timeFieldName} every ${interval}`, + meta: { + type: 'date', + }, + }, + { + id: 'rows', + name: 'rows', + meta: { + type: 'number', + }, + }, + ] as DatatableColumn[], + query: { + esql: histogramQuery, + }, + }; + const sug = lensSuggestionsApi(context, dataView, ['lnsDatatable']) ?? []; + if (sug.length) { + return sug[0]; + } + return undefined; + } + return undefined; + }, [currentSuggestion, dataView, query, timeRange, data, lensSuggestionsApi]); + useEffect(() => { const newSuggestionsDeps = getSuggestionDeps({ dataView, query, columns }); @@ -70,8 +139,9 @@ export const useLensSuggestions = ({ return { allSuggestions, - currentSuggestion, - suggestionUnsupported: !currentSuggestion && !dataView.isTimeBased(), + currentSuggestion: histogramSuggestion ?? currentSuggestion, + suggestionUnsupported: !currentSuggestion && !histogramSuggestion && isPlainRecord, + isOnHistogramMode: Boolean(histogramSuggestion), }; }; diff --git a/src/plugins/unified_histogram/public/layout/layout.tsx b/src/plugins/unified_histogram/public/layout/layout.tsx index 4d0605c4f72b3..d2088d4776445 100644 --- a/src/plugins/unified_histogram/public/layout/layout.tsx +++ b/src/plugins/unified_histogram/public/layout/layout.tsx @@ -13,7 +13,12 @@ import { createHtmlPortalNode, InPortal, OutPortal } from 'react-reverse-portal' import { css } from '@emotion/css'; import type { Datatable, DatatableColumn } from '@kbn/expressions-plugin/common'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; -import type { LensEmbeddableInput, LensSuggestionsApi, Suggestion } from '@kbn/lens-plugin/public'; +import type { + EmbeddableComponentProps, + LensEmbeddableInput, + LensSuggestionsApi, + Suggestion, +} from '@kbn/lens-plugin/public'; import { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; import { Chart } from '../chart'; import { Panels, PANELS_MODE } from '../panels'; @@ -156,6 +161,10 @@ export interface UnifiedHistogramLayoutProps extends PropsWithChildren * Callback to pass to the Lens embeddable to handle brush events */ onBrushEnd?: LensEmbeddableInput['onBrushEnd']; + /** + * Allows users to enable/disable default actions + */ + withDefaultActions?: EmbeddableComponentProps['withDefaultActions']; } export const UnifiedHistogramLayout = ({ @@ -192,16 +201,20 @@ export const UnifiedHistogramLayout = ({ onFilter, onBrushEnd, children, + withDefaultActions, }: UnifiedHistogramLayoutProps) => { - const { allSuggestions, currentSuggestion, suggestionUnsupported } = useLensSuggestions({ - dataView, - query, - originalSuggestion, - isPlainRecord, - columns, - lensSuggestionsApi, - onSuggestionChange, - }); + const { allSuggestions, currentSuggestion, suggestionUnsupported, isOnHistogramMode } = + useLensSuggestions({ + dataView, + query, + originalSuggestion, + isPlainRecord, + columns, + timeRange, + data: services.data, + lensSuggestionsApi, + onSuggestionChange, + }); const chart = suggestionUnsupported ? undefined : originalChart; @@ -277,6 +290,8 @@ export const UnifiedHistogramLayout = ({ onFilter={onFilter} onBrushEnd={onBrushEnd} lensTablesAdapter={lensTablesAdapter} + isOnHistogramMode={isOnHistogramMode} + withDefaultActions={withDefaultActions} /> {children} diff --git a/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx b/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx index 2b4f3257f2bf5..5cf4795e1ee75 100644 --- a/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx +++ b/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx @@ -535,7 +535,7 @@ storiesOf('SearchBar', module) ], } as unknown as SearchBarProps) ) - .add('with dataviewPicker with SQL', () => + .add('with dataviewPicker with ESQL', () => wrapSearchBarInContext({ dataViewPickerComponentProps: { currentDataViewId: '1234', @@ -547,66 +547,66 @@ storiesOf('SearchBar', module) onChangeDataView: action('onChangeDataView'), onAddField: action('onAddField'), onDataViewCreated: action('onDataViewCreated'), - textBasedLanguages: ['SQL'], + textBasedLanguages: ['ESQL'], }, } as SearchBarProps) ) - .add('with dataviewPicker with SQL and sql query', () => + .add('with dataviewPicker with ESQL and ESQL query', () => wrapSearchBarInContext({ dataViewPickerComponentProps: { currentDataViewId: '1234', trigger: { 'data-test-subj': 'dataView-switch-link', - label: 'SQL', - title: 'SQL', + label: 'ESQL', + title: 'ESQL', }, onChangeDataView: action('onChangeDataView'), onAddField: action('onAddField'), onDataViewCreated: action('onDataViewCreated'), - textBasedLanguages: ['SQL'], + textBasedLanguages: ['ESQL'], }, - query: { sql: 'SELECT field1, field2 FROM DATAVIEW' }, + query: { esql: 'from dataview | project field1, field2' }, } as unknown as SearchBarProps) ) - .add('with dataviewPicker with SQL and large sql query', () => + .add('with dataviewPicker with ESQL and large ESQL query', () => wrapSearchBarInContext({ dataViewPickerComponentProps: { currentDataViewId: '1234', trigger: { 'data-test-subj': 'dataView-switch-link', - label: 'SQL', - title: 'SQL', + label: 'ESQL', + title: 'ESQL', }, onChangeDataView: action('onChangeDataView'), onAddField: action('onAddField'), onDataViewCreated: action('onDataViewCreated'), - textBasedLanguages: ['SQL'], + textBasedLanguages: ['ESQL'], }, query: { - sql: 'SELECT field1, field2, field 3, field 4, field 5 FROM DATAVIEW WHERE field5 IS NOT NULL AND field4 IS NULL', + esql: 'from dataview | project field1, field2, field 3, field 4, field 5 | where field5 > 5 | stats var = avg(field3)', }, } as unknown as SearchBarProps) ) - .add('with dataviewPicker with SQL and errors in sql query', () => + .add('with dataviewPicker with ESQL and errors in ESQL query', () => wrapSearchBarInContext({ dataViewPickerComponentProps: { currentDataViewId: '1234', trigger: { 'data-test-subj': 'dataView-switch-link', - label: 'SQL', - title: 'SQL', + label: 'ESQL', + title: 'ESQL', }, onChangeDataView: action('onChangeDataView'), onAddField: action('onAddField'), onDataViewCreated: action('onDataViewCreated'), - textBasedLanguages: ['SQL'], + textBasedLanguages: ['ESQL'], }, textBasedLanguageModeErrors: [ new Error( - '[essql] > Unexpected error from Elasticsearch: verification_exception - Found 1 problem line 1:16: Unknown column [field10]' + '[esql] > Unexpected error from Elasticsearch: verification_exception - Found 1 problem line 1:16: Unknown column [field10]' ), ], - query: { sql: 'SELECT field1, field10 FROM DATAVIEW' }, + query: { esql: 'from dataview | project field10' }, } as unknown as SearchBarProps) ) .add('in disabled state', () => diff --git a/src/plugins/unified_search/public/actions/apply_filter_action.ts b/src/plugins/unified_search/public/actions/apply_filter_action.ts index 1797aa4a2fe85..0ccf1de9f41ae 100644 --- a/src/plugins/unified_search/public/actions/apply_filter_action.ts +++ b/src/plugins/unified_search/public/actions/apply_filter_action.ts @@ -38,11 +38,13 @@ async function isCompatible(context: ApplyGlobalFilterActionContext) { export function createFilterAction( filterManager: FilterManager, timeFilter: TimefilterContract, - theme: ThemeServiceSetup + theme: ThemeServiceSetup, + id: string = ACTION_GLOBAL_APPLY_FILTER, + type: string = ACTION_GLOBAL_APPLY_FILTER ): UiActionsActionDefinition { return { - type: ACTION_GLOBAL_APPLY_FILTER, - id: ACTION_GLOBAL_APPLY_FILTER, + type, + id, order: 100, getIconType: () => 'filter', getDisplayName: () => { diff --git a/src/plugins/unified_search/public/dataview_picker/change_dataview.test.tsx b/src/plugins/unified_search/public/dataview_picker/change_dataview.test.tsx index be359f25a6496..7492018b3a6c2 100644 --- a/src/plugins/unified_search/public/dataview_picker/change_dataview.test.tsx +++ b/src/plugins/unified_search/public/dataview_picker/change_dataview.test.tsx @@ -137,8 +137,8 @@ describe('DataView component', () => { wrapDataViewComponentInContext( { ...props, - textBasedLanguages: [TextBasedLanguages.ESQL, TextBasedLanguages.SQL], - textBasedLanguage: TextBasedLanguages.SQL, + textBasedLanguages: [TextBasedLanguages.ESQL], + textBasedLanguage: TextBasedLanguages.ESQL, }, false ) diff --git a/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx b/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx index 72f777cfcae93..7d04fd5fa3621 100644 --- a/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx +++ b/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx @@ -11,6 +11,8 @@ import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { css } from '@emotion/react'; import { EuiPopover, + EuiPanel, + EuiBadge, EuiHorizontalRule, EuiButton, EuiContextMenuPanel, @@ -26,11 +28,11 @@ import { EuiToolTip, } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { AggregateQuery, getLanguageDisplayName } from '@kbn/es-query'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { IUnifiedSearchPluginServices } from '../types'; -import type { DataViewPickerPropsExtended } from './data_view_picker'; +import { type DataViewPickerPropsExtended } from './data_view_picker'; import type { DataViewListItemEnhanced } from './dataview_list'; -import type { TextBasedLanguagesListProps } from './text_languages_list'; import type { TextBasedLanguagesTransitionModalProps } from './text_languages_transition_modal'; import adhoc from './assets/adhoc.svg'; import { changeDataViewStyles } from './change_dataview.styles'; @@ -52,13 +54,6 @@ export const TextBasedLanguagesTransitionModal = ( ); -const LazyTextBasedLanguagesList = React.lazy(() => import('./text_languages_list')); -export const TextBasedLanguagesList = (props: TextBasedLanguagesListProps) => ( - }> - - -); - const mapAdHocDataView = (adHocDataView: DataView) => { return { title: adHocDataView.title, @@ -122,7 +117,7 @@ export function ChangeDataView({ useEffect(() => { if (textBasedLanguage) { - setTriggerLabel(textBasedLanguage.toUpperCase()); + setTriggerLabel(getLanguageDisplayName(textBasedLanguage).toUpperCase()); } else { setTriggerLabel(trigger.label); } @@ -245,7 +240,8 @@ export function ChangeDataView({ 'unifiedSearch.query.queryBar.indexPattern.textBasedLangSwitchWarning', { defaultMessage: - "Switching data views removes the current SQL query. Save this search to ensure you don't lose work.", + "Switching data views removes the current {textBasedLanguage} query. Save this search to ensure you don't lose work.", + values: { textBasedLanguage }, } )} > @@ -335,42 +331,24 @@ export function ChangeDataView({ if (textBasedLanguages?.length) { panelItems.push( , - - - -
    - {i18n.translate( - 'unifiedSearch.query.queryBar.indexPattern.textBasedLanguagesLabel', - { - defaultMessage: 'Text-based query languages', - } - )} -
    -
    -
    -
    , - { - setTriggerLabel(lang); - setPopoverIsOpen(false); - setIsTextBasedLangSelected(true); - // also update the query with the sql query - onTextLangQuerySubmit?.({ sql: `SELECT * FROM "${trigger.title}"` }); - }} - /> + + onTextBasedSubmit({ esql: `from ${trigger.title} | limit 10` })} + data-test-subj="select-text-based-language-panel" + > + {i18n.translate('unifiedSearch.query.queryBar.textBasedLanguagesTryLabel', { + defaultMessage: 'Try ES|QL', + })} + + {i18n.translate('unifiedSearch.query.queryBar.textBasedLanguagesTechPreviewLabel', { + defaultMessage: 'Technical preview', + })} + + + ); } @@ -384,6 +362,14 @@ export function ChangeDataView({ setIsTextLangTransitionModalDismissed(true); }, [storage]); + const onTextBasedSubmit = useCallback( + (q: AggregateQuery) => { + onTextLangQuerySubmit?.(q); + setPopoverIsOpen(false); + }, + [onTextLangQuerySubmit] + ); + const cleanup = useCallback( (shouldDismissModal: boolean) => { setIsTextLangTransitionModalVisible(false); @@ -434,6 +420,7 @@ export function ChangeDataView({ ); } diff --git a/src/plugins/unified_search/public/dataview_picker/explore_matching_button.tsx b/src/plugins/unified_search/public/dataview_picker/explore_matching_button.tsx index 77fe947061480..c02908007200f 100644 --- a/src/plugins/unified_search/public/dataview_picker/explore_matching_button.tsx +++ b/src/plugins/unified_search/public/dataview_picker/explore_matching_button.tsx @@ -35,7 +35,6 @@ export const ExploreMatchingButton = ({ alignItems="center" gutterSize="none" justifyContent="spaceBetween" - data-test-subj="select-text-based-language-panel" css={css` margin: ${euiTheme.size.s}; margin-bottom: 0; diff --git a/src/plugins/unified_search/public/dataview_picker/text_languages_list.test.tsx b/src/plugins/unified_search/public/dataview_picker/text_languages_list.test.tsx deleted file mode 100644 index deb619b236338..0000000000000 --- a/src/plugins/unified_search/public/dataview_picker/text_languages_list.test.tsx +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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, { MouseEvent } from 'react'; -import { EuiSelectable } from '@elastic/eui'; -import { act } from 'react-dom/test-utils'; -import { ShallowWrapper } from 'enzyme'; -import { shallowWithIntl as shallow } from '@kbn/test-jest-helpers'; -import TextBasedLanguagesList, { TextBasedLanguagesListProps } from './text_languages_list'; -import { TextBasedLanguages } from './data_view_picker'; - -function getTextLanguagesPickerList(instance: ShallowWrapper) { - return instance.find(EuiSelectable).first(); -} - -function getTextLanguagesPickerOptions(instance: ShallowWrapper) { - return getTextLanguagesPickerList(instance).prop('options'); -} - -function selectTextLanguagePickerOption(instance: ShallowWrapper, selectedLabel: string) { - const event = {} as MouseEvent; - const options: Array<{ label: string; checked?: 'on' | 'off' }> = getTextLanguagesPickerOptions( - instance - ).map((option: { label: string }) => - option.label === selectedLabel - ? { ...option, checked: 'on' } - : { ...option, checked: undefined } - ); - const selectedOption = { label: selectedLabel }; - return getTextLanguagesPickerList(instance).prop('onChange')!(options, event, selectedOption); -} - -describe('Text based languages list component', () => { - const changeLanguageSpy = jest.fn(); - let props: TextBasedLanguagesListProps; - beforeEach(() => { - props = { - selectedOption: 'ESQL', - onChange: changeLanguageSpy, - textBasedLanguages: [TextBasedLanguages.ESQL, TextBasedLanguages.SQL], - }; - }); - it('should trigger the onChange if a new language is selected', async () => { - const component = shallow(); - await act(async () => { - selectTextLanguagePickerOption(component, 'SQL'); - }); - expect(changeLanguageSpy).toHaveBeenCalled(); - }); - - it('should list all languages', () => { - const component = shallow(); - - expect(getTextLanguagesPickerOptions(component)!.map((option: any) => option.label)).toEqual([ - 'ESQL', - 'SQL', - ]); - }); -}); diff --git a/src/plugins/unified_search/public/dataview_picker/text_languages_list.tsx b/src/plugins/unified_search/public/dataview_picker/text_languages_list.tsx deleted file mode 100644 index ac4717ad40d48..0000000000000 --- a/src/plugins/unified_search/public/dataview_picker/text_languages_list.tsx +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { i18n } from '@kbn/i18n'; -import { EuiSelectable, EuiPanel, EuiBadge } from '@elastic/eui'; -import { TextBasedLanguages } from './data_view_picker'; - -export interface TextBasedLanguagesListProps { - textBasedLanguages: TextBasedLanguages[]; - onChange: (lang: string) => void; - selectedOption: string; -} - -// Needed for React.lazy -// eslint-disable-next-line import/no-default-export -export default function TextBasedLanguagesList({ - textBasedLanguages, - onChange, - selectedOption, -}: TextBasedLanguagesListProps) { - return ( - - key="textbasedLanguages-options" - data-test-subj="text-based-languages-switcher" - singleSelection="always" - options={textBasedLanguages.map((lang) => ({ - key: lang, - label: lang, - value: lang, - checked: lang === selectedOption ? 'on' : undefined, - append: ( - - {i18n.translate('unifiedSearch.query.queryBar.textBasedLanguagesTechPreviewLabel', { - defaultMessage: 'Technical preview', - })} - - ), - }))} - onChange={(choices) => { - const choice = choices.find(({ checked }) => checked) as unknown as { - value: string; - }; - onChange(choice.value); - }} - > - {(list) => ( - - {list} - - )} - - ); -} diff --git a/src/plugins/unified_search/public/dataview_picker/text_languages_transition_modal.tsx b/src/plugins/unified_search/public/dataview_picker/text_languages_transition_modal.tsx index f7eb0c4a74a22..c59599907456b 100644 --- a/src/plugins/unified_search/public/dataview_picker/text_languages_transition_modal.tsx +++ b/src/plugins/unified_search/public/dataview_picker/text_languages_transition_modal.tsx @@ -25,18 +25,21 @@ import { export interface TextBasedLanguagesTransitionModalProps { closeModal: (dismissFlag: boolean, needsSave?: boolean) => void; setIsTextLangTransitionModalVisible: (flag: boolean) => void; + textBasedLanguage?: string; } // Needed for React.lazy // eslint-disable-next-line import/no-default-export export default function TextBasedLanguagesTransitionModal({ closeModal, setIsTextLangTransitionModalVisible, + textBasedLanguage, }: TextBasedLanguagesTransitionModalProps) { const [dismissModalChecked, setDismissModalChecked] = useState(false); const onTransitionModalDismiss = useCallback((e) => { setDismissModalChecked(e.target.checked); }, []); + const language = textBasedLanguage?.toUpperCase(); return ( setIsTextLangTransitionModalVisible(false)} style={{ width: 700 }}> @@ -56,7 +59,8 @@ export default function TextBasedLanguagesTransitionModal({ 'unifiedSearch.query.queryBar.indexPattern.textBasedLanguagesTransitionModalBody', { defaultMessage: - "Switching data views removes the current SQL query. Save this search to ensure you don't lose work.", + "Switching data views removes the current {language} query. Save this search to ensure you don't lose work.", + values: { language }, } )} diff --git a/src/plugins/unified_search/public/index.ts b/src/plugins/unified_search/public/index.ts index b658a21d10cfd..fb689eb3e2d3b 100755 --- a/src/plugins/unified_search/public/index.ts +++ b/src/plugins/unified_search/public/index.ts @@ -30,6 +30,8 @@ export { ACTION_GLOBAL_APPLY_FILTER, UPDATE_FILTER_REFERENCES_ACTION } from './a export { UPDATE_FILTER_REFERENCES_TRIGGER } from './triggers'; export { createSearchBar } from './search_bar/create_search_bar'; +export { createFilterAction } from './actions/apply_filter_action'; + /* * Autocomplete query suggestions: */ diff --git a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx index 6e72baf29c7b1..0a20154b0d0b6 100644 --- a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx @@ -12,7 +12,12 @@ import React, { ReactNode, useCallback, useEffect, useMemo, useRef, useState } f import deepEqual from 'fast-deep-equal'; import useObservable from 'react-use/lib/useObservable'; import type { Filter, TimeRange, Query, AggregateQuery } from '@kbn/es-query'; -import { getAggregateQueryMode, isOfQueryType, isOfAggregateQueryType } from '@kbn/es-query'; +import { + getAggregateQueryMode, + isOfQueryType, + isOfAggregateQueryType, + getLanguageDisplayName, +} from '@kbn/es-query'; import { TextBasedLangEditor } from '@kbn/text-based-languages/public'; import { EMPTY } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -79,13 +84,14 @@ const getWrapperWithTooltip = ( ) => { if (enableTooltip && query && isOfAggregateQueryType(query)) { const textBasedLanguage = getAggregateQueryMode(query); + const displayName = getLanguageDisplayName(textBasedLanguage); return ( {children} @@ -138,6 +144,7 @@ export interface QueryBarTopRowProps onFiltersUpdated?: (filters: Filter[]) => void; dataViewPickerComponentProps?: DataViewPickerProps; textBasedLanguageModeErrors?: Error[]; + textBasedLanguageModeWarning?: string; onTextBasedSavedAndExit?: ({ onSave }: OnSaveTextLanguageQueryProps) => void; filterBar?: React.ReactNode; showDatePickerAsBadge?: boolean; @@ -648,6 +655,7 @@ export const QueryBarTopRow = React.memo( expandCodeEditor={(status: boolean) => setCodeEditorIsExpanded(status)} isCodeEditorExpanded={codeEditorIsExpanded} errors={props.textBasedLanguageModeErrors} + warning={props.textBasedLanguageModeWarning} detectTimestamp={detectTimestamp} onTextLangQuerySubmit={() => onSubmit({ diff --git a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx index 0879a12f31cef..8ffca3fbb0bda 100644 --- a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx @@ -247,6 +247,7 @@ export function createSearchBar({ {...overrideDefaultBehaviors(props)} dataViewPickerComponentProps={props.dataViewPickerComponentProps} textBasedLanguageModeErrors={props.textBasedLanguageModeErrors} + textBasedLanguageModeWarning={props.textBasedLanguageModeWarning} onTextBasedSavedAndExit={props.onTextBasedSavedAndExit} displayStyle={props.displayStyle} isScreenshotMode={isScreenshotMode} diff --git a/src/plugins/unified_search/public/search_bar/search_bar.tsx b/src/plugins/unified_search/public/search_bar/search_bar.tsx index aa84d4136ed36..b2d3b5abc966c 100644 --- a/src/plugins/unified_search/public/search_bar/search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/search_bar.tsx @@ -104,6 +104,7 @@ export interface SearchBarOwnProps { fillSubmitButton?: boolean; dataViewPickerComponentProps?: DataViewPickerProps; textBasedLanguageModeErrors?: Error[]; + textBasedLanguageModeWarning?: string; onTextBasedSavedAndExit?: ({ onSave }: OnSaveTextLanguageQueryProps) => void; showSubmitButton?: boolean; submitButtonStyle?: QueryBarTopRowProps['submitButtonStyle']; @@ -597,6 +598,7 @@ class SearchBarUI extends C onFiltersUpdated={this.props.onFiltersUpdated} dataViewPickerComponentProps={this.props.dataViewPickerComponentProps} textBasedLanguageModeErrors={this.props.textBasedLanguageModeErrors} + textBasedLanguageModeWarning={this.props.textBasedLanguageModeWarning} onTextBasedSavedAndExit={this.props.onTextBasedSavedAndExit} showDatePickerAsBadge={this.shouldShowDatePickerAsBadge()} filterBar={filterBar} diff --git a/src/plugins/usage_collection/server/collector/types.ts b/src/plugins/usage_collection/server/collector/types.ts index ff5b7135ba5c0..50a04560e384b 100644 --- a/src/plugins/usage_collection/server/collector/types.ts +++ b/src/plugins/usage_collection/server/collector/types.ts @@ -21,7 +21,7 @@ export type { /** * Helper to find out whether to keep recursively looking or if we are on an end value */ -export type RecursiveMakeSchemaFrom = U extends object +export type RecursiveMakeSchemaFrom = U extends object ? Record extends U ? | { @@ -31,19 +31,21 @@ export type RecursiveMakeSchemaFrom = U extends object description: string; // Intentionally enforcing the descriptions here } & SchemaMetaOptional; } - | MakeSchemaFrom // But still allow being explicit in the definition if they want to. - : MakeSchemaFrom + | MakeSchemaFrom // But still allow being explicit in the definition if they want to. + : MakeSchemaFrom + : RequireMeta extends true + ? { type: PossibleSchemaTypes; _meta: { description: string } } : { type: PossibleSchemaTypes; _meta?: { description: string } }; /** * The `schema` property in {@link CollectorOptions} must match the output of * the `fetch` method. This type helps ensure that is correct */ -export type MakeSchemaFrom = { +export type MakeSchemaFrom = { // Using Required to enforce all optional keys in the object [Key in keyof Required]: Required[Key] extends Array - ? { type: 'array'; items: RecursiveMakeSchemaFrom } - : RecursiveMakeSchemaFrom[Key]>; + ? { type: 'array'; items: RecursiveMakeSchemaFrom } + : RecursiveMakeSchemaFrom[Key], RequireMeta>; }; /** diff --git a/src/plugins/visualizations/kibana.jsonc b/src/plugins/visualizations/kibana.jsonc index 22c6bd9dd32b2..69caa82b50030 100644 --- a/src/plugins/visualizations/kibana.jsonc +++ b/src/plugins/visualizations/kibana.jsonc @@ -34,7 +34,8 @@ "share", "spaces", "savedObjectsTaggingOss", - "serverless" + "serverless", + "noDataPage" ], "requiredBundles": [ "kibanaUtils", diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 3ca1672159f24..d2805b43ed468 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -64,6 +64,7 @@ import { ContentManagementPublicSetup, ContentManagementPublicStart, } from '@kbn/content-management-plugin/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import type { TypesSetup, TypesStart } from './vis_types'; import type { VisualizeServices } from './visualize_app/types'; import { @@ -166,6 +167,7 @@ export interface VisualizationsStartDeps { savedObjectsManagement: SavedObjectsManagementPluginStart; contentManagement: ContentManagementPublicStart; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } /** @@ -330,6 +332,7 @@ export class VisualizationsPlugin listingViewRegistry, unifiedSearch: pluginsStart.unifiedSearch, serverless: pluginsStart.serverless, + noDataPage: pluginsStart.noDataPage, }; params.element.classList.add('visAppWrapper'); diff --git a/src/plugins/visualizations/public/visualize_app/app.tsx b/src/plugins/visualizations/public/visualize_app/app.tsx index 70dd288fccaec..c7c73893eb438 100644 --- a/src/plugins/visualizations/public/visualize_app/app.tsx +++ b/src/plugins/visualizations/public/visualize_app/app.tsx @@ -14,6 +14,7 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import { AppMountParameters, CoreStart } from '@kbn/core/public'; import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; import { syncGlobalQueryStateWithUrl } from '@kbn/data-plugin/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { AnalyticsNoDataPageKibanaProvider, @@ -38,6 +39,7 @@ interface NoDataComponentProps { dataViews: DataViewsContract; dataViewEditor: DataViewEditorStart; onDataViewCreated: (dataView: unknown) => void; + noDataPage?: NoDataPagePluginStart; } const NoDataComponent = ({ @@ -45,11 +47,13 @@ const NoDataComponent = ({ dataViews, dataViewEditor, onDataViewCreated, + noDataPage, }: NoDataComponentProps) => { const analyticsServices = { coreStart: core, dataViews, dataViewEditor, + noDataPage, }; return ( @@ -65,6 +69,7 @@ export const VisualizeApp = ({ onAppLeave }: VisualizeAppProps) => { core, kbnUrlStateStorage, dataViewEditor, + noDataPage, }, } = useKibana(); const { pathname } = useLocation(); @@ -125,6 +130,7 @@ export const VisualizeApp = ({ onAppLeave }: VisualizeAppProps) => { dataViewEditor={dataViewEditor} dataViews={dataViews} onDataViewCreated={onDataViewCreated} + noDataPage={noDataPage} /> ); } diff --git a/src/plugins/visualizations/public/visualize_app/types.ts b/src/plugins/visualizations/public/visualize_app/types.ts index 90806f138f9b6..77f743aaeef77 100644 --- a/src/plugins/visualizations/public/visualize_app/types.ts +++ b/src/plugins/visualizations/public/visualize_app/types.ts @@ -41,6 +41,7 @@ import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public'; import type { SavedSearch, SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; import type { Vis, VisualizeEmbeddableContract, @@ -117,6 +118,7 @@ export interface VisualizeServices extends CoreStart { listingViewRegistry: ListingViewRegistry; unifiedSearch: UnifiedSearchPublicPluginStart; serverless?: ServerlessPluginStart; + noDataPage?: NoDataPagePluginStart; } export interface VisInstance { diff --git a/src/plugins/visualizations/tsconfig.json b/src/plugins/visualizations/tsconfig.json index c72d4fd24d7ea..e643d9fa1fd61 100644 --- a/src/plugins/visualizations/tsconfig.json +++ b/src/plugins/visualizations/tsconfig.json @@ -62,7 +62,8 @@ "@kbn/content-management-tabbed-table-list-view", "@kbn/content-management-table-list-view", "@kbn/content-management-utils", - "@kbn/serverless" + "@kbn/serverless", + "@kbn/no-data-page-plugin" ], "exclude": [ "target/**/*", diff --git a/src/setup_node_env/openssl_legacy_provider/index.js b/src/setup_node_env/openssl_legacy_provider/index.js new file mode 100644 index 0000000000000..159c2a5e62e9a --- /dev/null +++ b/src/setup_node_env/openssl_legacy_provider/index.js @@ -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. + */ +var branch = require('../../../package.json').branch; +var docsBranch = branch.match(/^\d\.\d\d?$/) || 'current'; +var openSSLLegacyProviderEnabled = require('./openssl_legacy_provider_enabled')(); + +if (openSSLLegacyProviderEnabled) { + console.log( + 'Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/' + + docsBranch + + '/production.html#openssl-legacy-provider' + ); +} diff --git a/src/setup_node_env/openssl_legacy_provider/openssl_legacy_provider_enabled.js b/src/setup_node_env/openssl_legacy_provider/openssl_legacy_provider_enabled.js new file mode 100644 index 0000000000000..8c9771b1bf521 --- /dev/null +++ b/src/setup_node_env/openssl_legacy_provider/openssl_legacy_provider_enabled.js @@ -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. + */ + +var crypto = require('crypto'); + +// The blowfish cipher is only available when node is running with the --openssl-legacy-provider flag +module.exports = function () { + return crypto.getCiphers().includes('blowfish'); +}; diff --git a/src/setup_node_env/openssl_legacy_provider/openssl_legacy_provider_enabled.test.js b/src/setup_node_env/openssl_legacy_provider/openssl_legacy_provider_enabled.test.js new file mode 100644 index 0000000000000..30772d00bb165 --- /dev/null +++ b/src/setup_node_env/openssl_legacy_provider/openssl_legacy_provider_enabled.test.js @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +var spawnSync = require('child_process').spawnSync; + +describe('openSSLLegacyProviderEnabled', function () { + function runLegacyProviderCheck(execOptions, nodeOptions) { + var result = spawnSync( + process.execPath, + (execOptions ? execOptions.split(' ') : []).concat([ + '-p', + "require('./openssl_legacy_provider_enabled')()", + ]), + { + env: { + NODE_OPTIONS: nodeOptions || '', + }, + encoding: 'utf-8', + cwd: __dirname, + } + ); + var stdout = result.stdout.trim(); + return stdout === 'true'; + } + + it('should be disabled by default', function () { + expect(runLegacyProviderCheck()).toBe(false); + }); + + describe('using NODE_OPTIONS', function () { + it('should be enabled when --openssl-legacy-provider is set', function () { + expect(runLegacyProviderCheck(null, '--openssl-legacy-provider')).toBe(true); + }); + + it('should be enabled when --openssl-legacy-provider is set after --no-openssl-legacy-provider', function () { + expect( + runLegacyProviderCheck(null, '--no-openssl-legacy-provider --openssl-legacy-provider') + ).toBe(true); + }); + + it('should be disabled when --no-openssl-legacy-provider is set', function () { + expect(runLegacyProviderCheck(null, '--no-openssl-legacy-provider')).toBe(false); + }); + + it('should be disabled when --no-openssl-legacy-provider is set after --openssl-legacy-provider', function () { + expect( + runLegacyProviderCheck(null, '--openssl-legacy-provider --no-openssl-legacy-provider') + ).toBe(false); + }); + }); + + describe('using exec arguments', function () { + it('should be enabled when --openssl-legacy-provider is set', function () { + expect(runLegacyProviderCheck('--openssl-legacy-provider')).toBe(true); + }); + + it('should be enabled when --openssl-legacy-provider is set after --no-openssl-legacy-provider', function () { + expect(runLegacyProviderCheck('--no-openssl-legacy-provider --openssl-legacy-provider')).toBe( + true + ); + }); + + it('should be disabled when --no-openssl-legacy-provider is set', function () { + expect(runLegacyProviderCheck('--no-openssl-legacy-provider')).toBe(false); + }); + + it('should be disabled when --no-openssl-legacy-provider is set after --openssl-legacy-provider', function () { + expect(runLegacyProviderCheck('--openssl-legacy-provider --no-openssl-legacy-provider')).toBe( + false + ); + }); + }); +}); diff --git a/src/setup_node_env/setup_env.js b/src/setup_node_env/setup_env.js index 08897eb5a78c5..7b37d98011cfb 100644 --- a/src/setup_node_env/setup_env.js +++ b/src/setup_node_env/setup_env.js @@ -14,3 +14,4 @@ require('./harden'); require('symbol-observable'); require('source-map-support').install(); require('./node_version_validator'); +require('./openssl_legacy_provider'); diff --git a/src/setup_node_env/tsconfig.json b/src/setup_node_env/tsconfig.json index ed753806b9f4f..931afbdfaf0a3 100644 --- a/src/setup_node_env/tsconfig.json +++ b/src/setup_node_env/tsconfig.json @@ -6,6 +6,7 @@ "include": [ "harden/**/*", "root/**/*", + "openssl_legacy_provider/**/*", "*.js", "*.ts", ], diff --git a/test/api_integration/apis/data_views/index.ts b/test/api_integration/apis/data_views/index.ts index 328c7c1162d1b..72fb1f780311b 100644 --- a/test/api_integration/apis/data_views/index.ts +++ b/test/api_integration/apis/data_views/index.ts @@ -21,5 +21,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./deprecations')); loadTestFile(require.resolve('./has_user_index_pattern')); loadTestFile(require.resolve('./swap_references')); + loadTestFile(require.resolve('./resolve_index')); }); } diff --git a/test/api_integration/apis/data_views/resolve_index/index.ts b/test/api_integration/apis/data_views/resolve_index/index.ts new file mode 100644 index 0000000000000..846c6a485070f --- /dev/null +++ b/test/api_integration/apis/data_views/resolve_index/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('/internal/index-pattern-management/resolve_index', () => { + loadTestFile(require.resolve('./resolve_index')); + }); +} diff --git a/test/api_integration/apis/data_views/resolve_index/resolve_index.ts b/test/api_integration/apis/data_views/resolve_index/resolve_index.ts new file mode 100644 index 0000000000000..31039ed320111 --- /dev/null +++ b/test/api_integration/apis/data_views/resolve_index/resolve_index.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +// node scripts/functional_tests --config test/api_integration/config.js --grep="Resolve index API" + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('Resolve index API', function () { + it('should return 200 for a search for indices with wildcard', () => + supertest.get(`/internal/index-pattern-management/resolve_index/test*`).expect(200)); + + it('should return 404 for an exact match index', () => + supertest.get(`/internal/index-pattern-management/resolve_index/test`).expect(404)); + }); +} diff --git a/test/api_integration/apis/telemetry/telemetry_config.ts b/test/api_integration/apis/telemetry/telemetry_config.ts index a9a04a3986ba7..61a500cef1452 100644 --- a/test/api_integration/apis/telemetry/telemetry_config.ts +++ b/test/api_integration/apis/telemetry/telemetry_config.ts @@ -46,6 +46,7 @@ export default function telemetryConfigTest({ getService }: FtrProviderContext) optIn: null, // the config.js for this FTR sets it to `false`, we are bound to ask again. sendUsageFrom: 'server', telemetryNotifyUserAboutOptInDefault: false, // it's not opted-in by default (that's what this flag is about) + labels: {}, }); }); @@ -69,6 +70,7 @@ export default function telemetryConfigTest({ getService }: FtrProviderContext) optIn: true, sendUsageFrom: 'server', telemetryNotifyUserAboutOptInDefault: false, + labels: {}, }); }); @@ -92,6 +94,7 @@ export default function telemetryConfigTest({ getService }: FtrProviderContext) optIn: false, sendUsageFrom: 'server', telemetryNotifyUserAboutOptInDefault: false, + labels: {}, }); }); @@ -136,6 +139,7 @@ export default function telemetryConfigTest({ getService }: FtrProviderContext) optIn: true, sendUsageFrom: 'server', telemetryNotifyUserAboutOptInDefault: false, + labels: {}, }); }); @@ -158,6 +162,7 @@ export default function telemetryConfigTest({ getService }: FtrProviderContext) optIn: null, sendUsageFrom: 'server', telemetryNotifyUserAboutOptInDefault: false, + labels: {}, }); }); }); diff --git a/test/api_integration/apis/ui_counters/ui_counters.ts b/test/api_integration/apis/ui_counters/ui_counters.ts index 9d3bfa9c25b81..db75c82f293ac 100644 --- a/test/api_integration/apis/ui_counters/ui_counters.ts +++ b/test/api_integration/apis/ui_counters/ui_counters.ts @@ -56,8 +56,7 @@ export default function ({ getService }: FtrProviderContext) { return savedObject; }; - // FLAKY: https://github.com/elastic/kibana/issues/98240 - describe.skip('UI Counters API', () => { + describe('UI Counters API', () => { const dayDate = moment().format('DDMMYYYY'); before(async () => await esArchiver.emptyKibanaIndex()); diff --git a/test/examples/search/warnings.ts b/test/examples/search/warnings.ts index 24656ed68285c..c1c86863ad7a8 100644 --- a/test/examples/search/warnings.ts +++ b/test/examples/search/warnings.ts @@ -167,6 +167,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // click "see full error" button in the toast const [openShardModalButton] = await testSubjects.findAll('openShardFailureModalBtn'); await openShardModalButton.click(); + await testSubjects.exists('shardFailureModalTitle'); const modalHeader = await testSubjects.find('shardFailureModalTitle'); expect(await modalHeader.getVisibleText()).to.be('2 of 4 shards failed'); // request diff --git a/test/functional/apps/console/_autocomplete.ts b/test/functional/apps/console/_autocomplete.ts index af5e9e6741197..8f2a927a4ff24 100644 --- a/test/functional/apps/console/_autocomplete.ts +++ b/test/functional/apps/console/_autocomplete.ts @@ -14,7 +14,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); const retry = getService('retry'); - const PageObjects = getPageObjects(['common', 'console']); + const PageObjects = getPageObjects(['common', 'console', 'header']); const find = getService('find'); describe('console autocomplete feature', function describeIndexTests() { @@ -44,11 +44,160 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(PageObjects.console.isAutocompleteVisible()).to.be.eql(true); }); + // FLAKY: https://github.com/elastic/kibana/issues/165465 + describe.skip('Autocomplete behavior', () => { + beforeEach(async () => { + await PageObjects.console.clearTextArea(); + await PageObjects.console.pressEnter(); + }); + + it('HTTP methods', async () => { + const suggestions = { + G: ['GET'], + P: ['PUT', 'POST'], + D: ['DELETE'], + H: ['HEAD'], + }; + for (const [char, methods] of Object.entries(suggestions)) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.enterText(char); + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.isAutocompleteVisible() + ); + expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true); + + for (const [i, method] of methods.entries()) { + expect(await PageObjects.console.getAutocompleteSuggestion(i)).to.be.eql(method); + } + + await PageObjects.console.pressEscape(); + await PageObjects.console.pressEnter(); + } + }); + + it('ES API endpoints', async () => { + const suggestions = { + 'GET _': ['_alias', '_all'], + 'PUT _': ['_all'], + 'POST _': ['_aliases', '_all'], + 'DELETE _': ['_all'], + 'HEAD _': ['_alias', '_all'], + }; + for (const [text, endpoints] of Object.entries(suggestions)) { + for (const char of text) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.enterText(char); + } + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.isAutocompleteVisible() + ); + expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true); + + for (const [i, endpoint] of endpoints.entries()) { + expect(await PageObjects.console.getAutocompleteSuggestion(i)).to.be.eql(endpoint); + } + + await PageObjects.console.pressEscape(); + await PageObjects.console.pressEnter(); + } + }); + + it('JSON autocompletion with placeholder fields', async () => { + await PageObjects.console.enterText('GET _search\n{'); + await PageObjects.console.pressEnter(); + + for (const char of '"ag') { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.enterText(char); + } + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.isAutocompleteVisible() + ); + expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true); + await PageObjects.console.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); + + expect(await PageObjects.console.getAllVisibleText()).to.be.eql( + ` +GET _search +{ + "aggs": { + "NAME": { + "AGG_TYPE": {} + } + } +} +`.replace(/\n/g, '') + ); + // cursor should be located between '"' and 'N' + expect(await PageObjects.console.getCurrentLineNumber()).to.be.eql(5); + + await PageObjects.console.pressDown(); + await PageObjects.console.pressRight(); + await PageObjects.console.pressRight(); + for (let i = 0; i < 8; i++) { + await PageObjects.console.pressRight(true); // select 'AGG_TYPE' + } + + for (const char of 'ter') { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.enterText(char); + } + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.isAutocompleteVisible() + ); + expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true); + await PageObjects.console.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); + + expect(await PageObjects.console.getAllVisibleText()).to.be.eql( + ` +GET _search +{ + "aggs": { + "NAME": { + "terms": { + "field": "" + } + } + } +} +`.replace(/\n/g, '') + ); + }); + + it('Dynamic autocomplete', async () => { + await PageObjects.console.enterRequest('POST test/_doc\n{}'); + await PageObjects.console.clickPlay(); + + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await PageObjects.console.getResponseStatus()).to.be('201'); + + await PageObjects.console.pressEnter(); + for (const char of 'POST t') { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.enterText(char); + } + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.isAutocompleteVisible() + ); + expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true); + + expect(await PageObjects.console.getAutocompleteSuggestion(0)).to.be.eql('test'); + }); + }); + // FLAKY: https://github.com/elastic/kibana/issues/164584 describe.skip('anti-regression watchdogs', () => { beforeEach(async () => { await PageObjects.console.clearTextArea(); - await PageObjects.console.pressEnter(); }); it('should suppress auto-complete on arrow keys', async () => { @@ -92,7 +241,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { for (const method of methods) { await PageObjects.console.clearTextArea(); - await PageObjects.console.pressEnter(); for (const char of method.slice(0, -1)) { await PageObjects.console.sleepForDebouncePeriod(); diff --git a/test/functional/apps/dashboard/group1/dashboard_unsaved_listing.ts b/test/functional/apps/dashboard/group1/dashboard_unsaved_listing.ts index 6a6294d1869d1..73e97aab3cb36 100644 --- a/test/functional/apps/dashboard/group1/dashboard_unsaved_listing.ts +++ b/test/functional/apps/dashboard/group1/dashboard_unsaved_listing.ts @@ -102,14 +102,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('does not show unsaved changes on new dashboard when no panels have been added', async () => { - await PageObjects.dashboard.expectUnsavedChangesDoesNotExist(unsavedDashboardTitle); + await PageObjects.dashboard.expectUnsavedChangesListingDoesNotExist(unsavedDashboardTitle); }); it('can discard unsaved changes using the discard link', async () => { await PageObjects.dashboard.clickUnsavedChangesDiscard( `discard-unsaved-${dashboardTitle.split(' ').join('-')}` ); - await PageObjects.dashboard.expectUnsavedChangesDoesNotExist(dashboardTitle); + await PageObjects.dashboard.expectUnsavedChangesListingDoesNotExist(dashboardTitle); await PageObjects.dashboard.loadSavedDashboard(dashboardTitle); await PageObjects.dashboard.switchToEditMode(); const currentPanelCount = await PageObjects.dashboard.getPanelCount(); @@ -132,7 +132,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.dashboard.saveDashboard(newDashboartTitle); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.dashboard.gotoDashboardLandingPage(); - await PageObjects.dashboard.expectUnsavedChangesDoesNotExist(unsavedDashboardTitle); + await PageObjects.dashboard.expectUnsavedChangesListingDoesNotExist(unsavedDashboardTitle); }); it('does not list unsaved changes when unsaved version of the dashboard is the same', async () => { @@ -167,7 +167,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Check that it now does not exist await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.dashboard.expectUnsavedChangesDoesNotExist(newDashboartTitle); + await PageObjects.dashboard.expectUnsavedChangesListingDoesNotExist(newDashboartTitle); }); }); } diff --git a/test/functional/apps/discover/group2/_data_grid_footer.ts b/test/functional/apps/discover/group2/_data_grid_footer.ts index a1d2ff0294d23..4cc7b96a52607 100644 --- a/test/functional/apps/discover/group2/_data_grid_footer.ts +++ b/test/functional/apps/discover/group2/_data_grid_footer.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; -const FOOTER_SELECTOR = 'discoverTableFooter'; +const FOOTER_SELECTOR = 'unifiedDataTableFooter'; const LOAD_MORE_SELECTOR = 'dscGridSampleSizeFetchMoreLink'; export default function ({ getService, getPageObjects }: FtrProviderContext) { diff --git a/test/functional/apps/discover/group2/_data_grid_pagination.ts b/test/functional/apps/discover/group2/_data_grid_pagination.ts index 7da02308c73be..4d0c81c4cfebc 100644 --- a/test/functional/apps/discover/group2/_data_grid_pagination.ts +++ b/test/functional/apps/discover/group2/_data_grid_pagination.ts @@ -52,18 +52,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should show footer only for the last page', async () => { // footer is not shown - await testSubjects.missingOrFail('discoverTableFooter'); + await testSubjects.missingOrFail('unifiedDataTableFooter'); // go to next page await testSubjects.click('pagination-button-next'); // footer is not shown yet await retry.try(async function () { - await testSubjects.missingOrFail('discoverTableFooter'); + await testSubjects.missingOrFail('unifiedDataTableFooter'); }); // go to the last page await testSubjects.click('pagination-button-4'); // footer is shown now await retry.try(async function () { - await testSubjects.existOrFail('discoverTableFooter'); + await testSubjects.existOrFail('unifiedDataTableFooter'); }); }); @@ -80,7 +80,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async function () { return !testSubjects.exists('pagination-button-1'); // only page 0 is left }); - await testSubjects.existOrFail('discoverTableFooter'); + await testSubjects.existOrFail('unifiedDataTableFooter'); }); it('should render exact number of rows which where configured in the saved search or in settings', async () => { diff --git a/test/functional/apps/discover/group2/_sql_view.ts b/test/functional/apps/discover/group2/_esql_view.ts similarity index 77% rename from test/functional/apps/discover/group2/_sql_view.ts rename to test/functional/apps/discover/group2/_esql_view.ts index 95ce1516728d2..1f7493b6ff905 100644 --- a/test/functional/apps/discover/group2/_sql_view.ts +++ b/test/functional/apps/discover/group2/_esql_view.ts @@ -28,10 +28,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const defaultSettings = { defaultIndex: 'logstash-*', - 'discover:enableSql': true, + 'discover:enableESQL': true, }; - describe('discover sql view', async function () { + describe('discover esql view', async function () { before(async () => { await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']); log.debug('load kibana index with default index pattern'); @@ -44,7 +44,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); describe('test', () => { - it('should render sql view correctly', async function () { + it('should render esql view correctly', async function () { await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); expect(await testSubjects.exists('showQueryBarMenu')).to.be(true); @@ -62,7 +62,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.click('field-@message-showDetails'); expect(await testSubjects.exists('discoverFieldListPanelEdit-@message')).to.be(true); - await PageObjects.discover.selectTextBaseLang('SQL'); + await PageObjects.discover.selectTextBaseLang(); await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); expect(await testSubjects.exists('fieldListFiltersFieldSearch')).to.be(true); @@ -72,12 +72,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await testSubjects.exists('showQueryBarMenu')).to.be(false); expect(await testSubjects.exists('addFilter')).to.be(false); expect(await testSubjects.exists('dscViewModeDocumentButton')).to.be(false); - // when Lens suggests a table, we render the histogram + // when Lens suggests a table, we render an ESQL based histogram expect(await testSubjects.exists('unifiedHistogramChart')).to.be(true); expect(await testSubjects.exists('unifiedHistogramQueryHits')).to.be(true); expect(await testSubjects.exists('discoverAlertsButton')).to.be(false); expect(await testSubjects.exists('shareTopNavButton')).to.be(true); - expect(await testSubjects.exists('dataGridColumnSortingButton')).to.be(true); + expect(await testSubjects.exists('dataGridColumnSortingButton')).to.be(false); expect(await testSubjects.exists('docTableExpandToggleColumn')).to.be(true); expect(await testSubjects.exists('fieldListFiltersFieldTypeFilterToggle')).to.be(true); await testSubjects.click('field-@message-showDetails'); @@ -85,33 +85,27 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should perform test query correctly', async function () { - await PageObjects.discover.selectTextBaseLang('SQL'); - const testQuery = `SELECT "@tags", geo.dest, count(*) occurred FROM "logstash-*" - GROUP BY "@tags", geo.dest - HAVING occurred > 20 - ORDER BY occurred DESC`; + await PageObjects.discover.selectTextBaseLang(); + const testQuery = `from logstash-* | limit 10 | stats countB = count(bytes) by geo.dest | sort countB`; await monacoEditor.setCodeEditorValue(testQuery); await testSubjects.click('querySubmitButton'); await PageObjects.header.waitUntilLoadingHasFinished(); - // here Lens suggests a heatmap so it is rendered + // here Lens suggests a XY so it is rendered expect(await testSubjects.exists('unifiedHistogramChart')).to.be(true); - expect(await testSubjects.exists('heatmapChart')).to.be(true); - const cell = await dataGrid.getCellElement(0, 4); - expect(await cell.getVisibleText()).to.be('2269'); + expect(await testSubjects.exists('xyVisChart')).to.be(true); + const cell = await dataGrid.getCellElement(0, 2); + expect(await cell.getVisibleText()).to.be('1'); }); it('should render when switching to a time range with no data, then back to a time range with data', async () => { - await PageObjects.discover.selectTextBaseLang('SQL'); - const testQuery = `SELECT "@tags", geo.dest, count(*) occurred FROM "logstash-*" - GROUP BY "@tags", geo.dest - HAVING occurred > 20 - ORDER BY occurred DESC`; + await PageObjects.discover.selectTextBaseLang(); + const testQuery = `from logstash-* | limit 10 | stats countB = count(bytes) by geo.dest | sort countB`; await monacoEditor.setCodeEditorValue(testQuery); await testSubjects.click('querySubmitButton'); await PageObjects.header.waitUntilLoadingHasFinished(); - let cell = await dataGrid.getCellElement(0, 4); - expect(await cell.getVisibleText()).to.be('2269'); + let cell = await dataGrid.getCellElement(0, 2); + expect(await cell.getVisibleText()).to.be('1'); await PageObjects.timePicker.setAbsoluteRange( 'Sep 19, 2015 @ 06:31:44.000', 'Sep 19, 2015 @ 06:31:44.000' @@ -120,23 +114,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await testSubjects.exists('discoverNoResults')).to.be(true); await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.header.waitUntilLoadingHasFinished(); - cell = await dataGrid.getCellElement(0, 4); - expect(await cell.getVisibleText()).to.be('2269'); + cell = await dataGrid.getCellElement(0, 2); + expect(await cell.getVisibleText()).to.be('1'); }); it('should query an index pattern that doesnt translate to a dataview correctly', async function () { - await PageObjects.discover.selectTextBaseLang('SQL'); - const testQuery = `SELECT "@tags", geo.dest, count(*) occurred FROM "logstash*" - GROUP BY "@tags", geo.dest - HAVING occurred > 20 - ORDER BY occurred DESC`; + await PageObjects.discover.selectTextBaseLang(); + const testQuery = `from logstash* | limit 10 | stats countB = count(bytes) by geo.dest | sort countB`; await monacoEditor.setCodeEditorValue(testQuery); await testSubjects.click('querySubmitButton'); await PageObjects.header.waitUntilLoadingHasFinished(); - const cell = await dataGrid.getCellElement(0, 4); - expect(await cell.getVisibleText()).to.be('2269'); + const cell = await dataGrid.getCellElement(0, 2); + expect(await cell.getVisibleText()).to.be('1'); }); }); }); diff --git a/test/functional/apps/discover/group2/index.ts b/test/functional/apps/discover/group2/index.ts index 17562157f444e..163c6b1a9f205 100644 --- a/test/functional/apps/discover/group2/index.ts +++ b/test/functional/apps/discover/group2/index.ts @@ -32,7 +32,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_data_grid_pagination')); loadTestFile(require.resolve('./_data_grid_footer')); loadTestFile(require.resolve('./_adhoc_data_views')); - loadTestFile(require.resolve('./_sql_view')); + loadTestFile(require.resolve('./_esql_view')); loadTestFile(require.resolve('./_indexpattern_with_unmapped_fields')); loadTestFile(require.resolve('./_runtime_fields_editor')); loadTestFile(require.resolve('./_huge_fields')); diff --git a/test/functional/apps/discover/group3/_request_counts.ts b/test/functional/apps/discover/group3/_request_counts.ts index c1224596d3e00..fdee64ada9965 100644 --- a/test/functional/apps/discover/group3/_request_counts.ts +++ b/test/functional/apps/discover/group3/_request_counts.ts @@ -38,7 +38,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*', 'bfetch:disable': true, - 'discover:enableSql': true, + 'discover:enableESQL': true, }); await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); }); @@ -54,7 +54,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.header.waitUntilLoadingHasFinished(); }); - const getSearchCount = async (type: 'ese' | 'sql') => { + const getSearchCount = async (type: 'ese' | 'esql') => { const requests = await browser.execute(() => performance .getEntries() @@ -69,7 +69,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await elasticChart.canvasExists(); }; - const expectSearches = async (type: 'ese' | 'sql', expected: number, cb: Function) => { + const expectSearches = async (type: 'ese' | 'esql', expected: number, cb: Function) => { await browser.execute(async () => { performance.clearResourceTimings(); }); @@ -86,12 +86,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { savedSearch, query1, query2, + savedSearchesRequests, setQuery, }: { - type: 'ese' | 'sql'; + type: 'ese' | 'esql'; savedSearch: string; query1: string; query2: string; + savedSearchesRequests?: number; setQuery: (query: string) => Promise; }) => { it('should send 2 search requests (documents + chart) on page load', async () => { @@ -143,8 +145,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'Sep 23, 2015 @ 00:00:00.000' ); await waitForLoadingToFinish(); + // TODO: Check why the request happens 4 times in case of opening a saved search + // https://github.com/elastic/kibana/issues/165192 // creating the saved search - await expectSearches(type, 2, async () => { + await expectSearches(type, savedSearchesRequests ?? 2, async () => { await PageObjects.discover.saveSearch(savedSearch); }); // resetting the saved search @@ -160,7 +164,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await waitForLoadingToFinish(); }); // loading the saved search - await expectSearches(type, 2, async () => { + // TODO: https://github.com/elastic/kibana/issues/165192 + await expectSearches(type, savedSearchesRequests ?? 2, async () => { await PageObjects.discover.loadSavedSearch(savedSearch); }); }); @@ -218,21 +223,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - describe('SQL mode', () => { - const type = 'sql'; + describe('ES|QL mode', () => { + const type = 'esql'; beforeEach(async () => { - await PageObjects.discover.selectTextBaseLang('SQL'); - monacoEditor.setCodeEditorValue('SELECT count(*) FROM "logstash-*" WHERE bytes > 1000'); + await PageObjects.discover.selectTextBaseLang(); + monacoEditor.setCodeEditorValue( + 'from logstash-* | where bytes > 1000 | stats countB = count(bytes)' + ); await queryBar.clickQuerySubmitButton(); await waitForLoadingToFinish(); }); getSharedTests({ type, - savedSearch: 'sql test', - query1: 'SELECT type, count(*) FROM "logstash-*" WHERE bytes > 1000 GROUP BY type', - query2: 'SELECT type, count(*) FROM "logstash-*" WHERE bytes < 2000 GROUP BY type', + savedSearch: 'esql test', + query1: 'from logstash-* | where bytes > 1000 | stats countB = count(bytes) ', + query2: 'from logstash-* | where bytes < 2000 | stats countB = count(bytes) ', + savedSearchesRequests: 4, setQuery: (query) => monacoEditor.setCodeEditorValue(query), }); }); diff --git a/test/functional/apps/discover/group3/_sidebar.ts b/test/functional/apps/discover/group3/_sidebar.ts index 265466b5c67f9..eefda4891390b 100644 --- a/test/functional/apps/discover/group3/_sidebar.ts +++ b/test/functional/apps/discover/group3/_sidebar.ts @@ -96,7 +96,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should show filters by type in text-based view', async function () { - await kibanaServer.uiSettings.update({ 'discover:enableSql': true }); + await kibanaServer.uiSettings.update({ 'discover:enableESQL': true }); await browser.refresh(); await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); @@ -105,7 +105,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(options).to.have.length(6); await PageObjects.unifiedFieldList.closeSidebarFieldFilter(); - await PageObjects.discover.selectTextBaseLang('SQL'); + await PageObjects.discover.selectTextBaseLang(); await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); await PageObjects.unifiedFieldList.openSidebarFieldFilter(); @@ -113,7 +113,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(options).to.have.length(3); expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be( - '50 selected fields. 51 available fields.' + '82 available fields.' ); await testSubjects.click('typeFilter-number'); @@ -121,7 +121,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.waitFor('updates', async () => { return ( (await PageObjects.unifiedFieldList.getSidebarAriaDescription()) === - '6 selected fields. 6 available fields.' + '6 available fields.' ); }); }); @@ -366,7 +366,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should show selected and available fields in text-based mode', async function () { - await kibanaServer.uiSettings.update({ 'discover:enableSql': true }); + await kibanaServer.uiSettings.update({ 'discover:enableESQL': true }); await browser.refresh(); await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); @@ -375,24 +375,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { INITIAL_FIELD_LIST_SUMMARY ); - await PageObjects.discover.selectTextBaseLang('SQL'); + await PageObjects.discover.selectTextBaseLang(); await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be( - '50 selected fields. 51 available fields.' + '82 available fields.' ); await PageObjects.unifiedFieldList.clickFieldListItemRemove('extension'); await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be( - '49 selected fields. 51 available fields.' + '82 available fields.' ); - const testQuery = `SELECT "@tags", geo.dest, count(*) occurred FROM "logstash-*" - GROUP BY "@tags", geo.dest - HAVING occurred > 20 - ORDER BY occurred DESC`; + const testQuery = `from logstash-* | limit 10 | stats countB = count(bytes) by geo.dest | sort countB`; await monacoEditor.setCodeEditorValue(testQuery); await testSubjects.click('querySubmitButton'); @@ -400,11 +397,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be( - '3 selected fields. 3 available fields.' + '2 selected fields. 2 available fields.' ); expect( (await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected')).join(', ') - ).to.be('@tags, geo.dest, occurred'); + ).to.be('countB, geo.dest'); await PageObjects.unifiedSearch.switchDataView( 'discover-dataView-switch-link', diff --git a/test/functional/apps/home/_home.js b/test/functional/apps/home/_home.ts similarity index 90% rename from test/functional/apps/home/_home.js rename to test/functional/apps/home/_home.ts index e3ca3f6761113..32248c224ae3f 100644 --- a/test/functional/apps/home/_home.js +++ b/test/functional/apps/home/_home.ts @@ -7,8 +7,9 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; -export default function ({ getService, getPageObjects }) { +export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); const globalNav = getService('globalNav'); const testSubjects = getService('testSubjects'); diff --git a/test/functional/apps/home/_newsfeed.ts b/test/functional/apps/home/_newsfeed.ts index 3bbf0633594ac..468fb370d1961 100644 --- a/test/functional/apps/home/_newsfeed.ts +++ b/test/functional/apps/home/_newsfeed.ts @@ -13,8 +13,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const globalNav = getService('globalNav'); const PageObjects = getPageObjects(['newsfeed', 'common']); - // FLAKY: https://github.com/elastic/kibana/issues/135251 - describe.skip('Newsfeed', () => { + describe('Newsfeed', () => { before(async () => { await PageObjects.newsfeed.resetPage(); }); diff --git a/test/functional/apps/home/index.js b/test/functional/apps/home/index.ts similarity index 85% rename from test/functional/apps/home/index.js rename to test/functional/apps/home/index.ts index 307d848484724..75629a984df20 100644 --- a/test/functional/apps/home/index.js +++ b/test/functional/apps/home/index.ts @@ -6,7 +6,9 @@ * Side Public License, v 1. */ -export default function ({ getService, loadTestFile }) { +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { const browser = getService('browser'); describe('home app', function () { diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/hidden_types/data.json b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_types/data.json index 3dfde2c248862..d4929d3201878 100644 --- a/test/functional/fixtures/es_archiver/saved_objects_management/hidden_types/data.json +++ b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_types/data.json @@ -9,7 +9,6 @@ "title": "hidden object 1" }, "type": "test-actions-export-hidden", - "migrationVersion": {}, "updated_at": "2018-12-21T00:43:07.096Z" } } @@ -26,7 +25,6 @@ "title": "hidden object 2" }, "type": "test-actions-export-hidden", - "migrationVersion": {}, "updated_at": "2018-12-21T00:43:07.096Z" } } diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts index 11153db065a82..1424d952653cd 100644 --- a/test/functional/page_objects/common_page.ts +++ b/test/functional/page_objects/common_page.ts @@ -109,6 +109,18 @@ export class CommonPageObject extends FtrService { ? await this.loginIfPrompted(appUrl, insertTimestamp, disableWelcomePrompt) : await this.browser.getCurrentUrl(); + if ( + currentUrl.includes('/app/home') && + disableWelcomePrompt && + (await this.isWelcomeScreen()) + ) { + await this.browser.setLocalStorageItem('home:welcome:show', 'false'); + // Force a new navigation again + const msg = `Found the Welcome page in ${currentUrl}. Skipping it...`; + this.log.debug(msg); + throw new Error(msg); + } + if (ensureCurrentUrl && !currentUrl.includes(appUrl)) { throw new Error(`expected ${currentUrl}.includes(${appUrl})`); } @@ -274,7 +286,7 @@ export class CommonPageObject extends FtrService { appName === 'home' && currentUrl.includes('app/home') && disableWelcomePrompt && - (await this.isChromeHidden()) + (await this.isWelcomeScreen()) ) { await this.browser.setLocalStorageItem('home:welcome:show', 'false'); const msg = `Failed to skip the Welcome page when navigating the app ${appName}`; @@ -505,6 +517,10 @@ export class CommonPageObject extends FtrService { } } + async isWelcomeScreen() { + return await this.testSubjects.exists('homeWelcomeInterstitial'); + } + /** * Get visible text of the Welcome Banner */ diff --git a/test/functional/page_objects/console_page.ts b/test/functional/page_objects/console_page.ts index 9efe80741621e..21a183c832606 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -150,6 +150,18 @@ export class ConsolePageObject extends FtrService { return !attribute.includes('display: none;'); } + public async getAutocompleteSuggestion(index: number = 0) { + const children1 = await this.find + .allByCssSelector('.ace_autocomplete .ace_line :nth-child(1)') + .catch(() => null); + const children2 = await this.find + .allByCssSelector('.ace_autocomplete .ace_line :nth-child(2)') + .catch(() => null); + if (!children1 || !children2) return null; + + return (await children1[index].getVisibleText()) + (await children2[index].getVisibleText()); + } + public async enterRequest(request: string = '\nGET _search') { const textArea = await this.getEditorTextArea(); await textArea.pressKeys(request); @@ -206,24 +218,24 @@ export class ConsolePageObject extends FtrService { await textArea.pressKeys(Key.ESCAPE); } - public async pressDown() { + public async pressDown(shift: boolean = false) { const textArea = await this.testSubjects.find('console-textarea'); - await textArea.pressKeys(Key.DOWN); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.DOWN] : Key.DOWN); } - public async pressLeft() { + public async pressLeft(shift: boolean = false) { const textArea = await this.testSubjects.find('console-textarea'); - await textArea.pressKeys(Key.LEFT); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.LEFT] : Key.LEFT); } - public async pressRight() { + public async pressRight(shift: boolean = false) { const textArea = await this.testSubjects.find('console-textarea'); - await textArea.pressKeys(Key.RIGHT); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.RIGHT] : Key.RIGHT); } - public async pressUp() { + public async pressUp(shift: boolean = false) { const textArea = await this.testSubjects.find('console-textarea'); - await textArea.pressKeys(Key.UP); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.UP] : Key.UP); } public async clearTextArea() { diff --git a/test/functional/page_objects/dashboard_page.ts b/test/functional/page_objects/dashboard_page.ts index 897ceb5564d93..36da398b59d1f 100644 --- a/test/functional/page_objects/dashboard_page.ts +++ b/test/functional/page_objects/dashboard_page.ts @@ -138,7 +138,7 @@ export class DashboardPageObject extends FtrService { await this.testSubjects.existOrFail(`edit-unsaved-${title.split(' ').join('-')}`); } - public async expectUnsavedChangesDoesNotExist(title: string) { + public async expectUnsavedChangesListingDoesNotExist(title: string) { this.log.debug(`Expect Unsaved Changes Listing Does Not Exist for `, title); await this.testSubjects.missingOrFail(`edit-unsaved-${title.split(' ').join('-')}`); } @@ -174,11 +174,6 @@ export class DashboardPageObject extends FtrService { await this.testSubjects.existOrFail('dashboardLandingPage'); } - public async clickDashboardBreadcrumbLink() { - this.log.debug('clickDashboardBreadcrumbLink'); - await this.testSubjects.click('breadcrumb dashboardListingBreadcrumb first'); - } - public async expectOnDashboard(expectedTitle: string) { await this.retry.waitFor( `last breadcrumb to have dashboard title: ${expectedTitle}`, @@ -192,19 +187,21 @@ export class DashboardPageObject extends FtrService { public async gotoDashboardLandingPage(ignorePageLeaveWarning = true) { this.log.debug('gotoDashboardLandingPage'); - const onPage = await this.onDashboardLandingPage(); - if (!onPage) { - await this.clickDashboardBreadcrumbLink(); - await this.retry.try(async () => { - const warning = await this.testSubjects.exists('confirmModalTitleText'); - if (warning) { - await this.testSubjects.click( - ignorePageLeaveWarning ? 'confirmModalConfirmButton' : 'confirmModalCancelButton' - ); - } - }); - await this.expectExistsDashboardLandingPage(); - } + if (await this.onDashboardLandingPage()) return; + + const breadcrumbLink = this.config.get('serverless') + ? 'breadcrumb breadcrumb-deepLinkId-dashboards' + : 'breadcrumb dashboardListingBreadcrumb first'; + await this.testSubjects.click(breadcrumbLink); + await this.retry.try(async () => { + const warning = await this.testSubjects.exists('confirmModalTitleText'); + if (warning) { + await this.testSubjects.click( + ignorePageLeaveWarning ? 'confirmModalConfirmButton' : 'confirmModalCancelButton' + ); + } + }); + await this.expectExistsDashboardLandingPage(); } public async clickClone() { @@ -336,6 +333,12 @@ export class DashboardPageObject extends FtrService { }); } + public async expectMissingUnsavedChangesBadge() { + await this.retry.try(async () => { + await this.testSubjects.missingOrFail('dashboardUnsavedChangesBadge'); + }); + } + public async clickNewDashboard(continueEditing = false) { const discardButtonExists = await this.testSubjects.exists('discardDashboardPromptButton'); if (!continueEditing && discardButtonExists) { diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 7ddd4f303d975..1545975667c60 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -500,11 +500,9 @@ export class DiscoverPageObject extends FtrService { return items; } - public async selectTextBaseLang(lang: 'SQL') { + public async selectTextBaseLang() { await this.testSubjects.click('discover-dataView-switch-link'); - await this.find.clickByCssSelector( - `[data-test-subj="text-based-languages-switcher"] [title="${lang}"]` - ); + await this.testSubjects.click('select-text-based-language-panel'); await this.header.waitUntilLoadingHasFinished(); } diff --git a/test/functional/page_objects/home_page.ts b/test/functional/page_objects/home_page.ts index ac942c70b5d90..61eb1f40c49e7 100644 --- a/test/functional/page_objects/home_page.ts +++ b/test/functional/page_objects/home_page.ts @@ -53,7 +53,9 @@ export class HomePageObject extends FtrService { } async isWelcomeInterstitialDisplayed() { - return await this.testSubjects.isDisplayed('homeWelcomeInterstitial'); + // give the interstitial enough time to fade in + await new Promise((resolve) => setTimeout(resolve, 500)); + return await this.testSubjects.isDisplayed('homeWelcomeInterstitial', 2000); } async isGuidedOnboardingLandingDisplayed() { diff --git a/test/functional/page_objects/newsfeed_page.ts b/test/functional/page_objects/newsfeed_page.ts index dd8eef67614bc..a130ffed57c77 100644 --- a/test/functional/page_objects/newsfeed_page.ts +++ b/test/functional/page_objects/newsfeed_page.ts @@ -21,7 +21,7 @@ export class NewsfeedPageObject extends FtrService { } async resetPage() { - await this.common.navigateToUrl('home', undefined); // navigateToApp sets `disableWelcomePrompt` to true under the hood. `navigateToUrl` explicitly disables the welcome screen. + await this.common.navigateToApp('home'); } async closeNewsfeedPanel() { diff --git a/test/functional/page_objects/time_picker.ts b/test/functional/page_objects/time_picker.ts index be43b0d2b29ec..495d4089321b4 100644 --- a/test/functional/page_objects/time_picker.ts +++ b/test/functional/page_objects/time_picker.ts @@ -92,7 +92,9 @@ export class TimePickerPageObject extends FtrService { * @param option 'Today' | 'This_week' | 'Last_15 minutes' | 'Last_24 hours' ... */ async setCommonlyUsedTime(option: CommonlyUsed | string) { + await this.testSubjects.exists('superDatePickerToggleQuickMenuButton', { timeout: 5000 }); await this.testSubjects.click('superDatePickerToggleQuickMenuButton'); + await this.testSubjects.exists(`superDatePickerCommonlyUsed_${option}`, { timeout: 5000 }); await this.testSubjects.click(`superDatePickerCommonlyUsed_${option}`); } diff --git a/test/functional/page_objects/time_to_visualize_page.ts b/test/functional/page_objects/time_to_visualize_page.ts index 57a22103f6409..91864a7995779 100644 --- a/test/functional/page_objects/time_to_visualize_page.ts +++ b/test/functional/page_objects/time_to_visualize_page.ts @@ -43,7 +43,7 @@ export class TimeToVisualizePageObject extends FtrService { public async resetNewDashboard() { await this.common.navigateToApp('dashboard'); - await this.dashboard.gotoDashboardLandingPage(true); + await this.dashboard.gotoDashboardLandingPage(); await this.dashboard.clickNewDashboard(false); } diff --git a/test/functional/services/common/browser.ts b/test/functional/services/common/browser.ts index fd46e5ac1448b..0a1798442f360 100644 --- a/test/functional/services/common/browser.ts +++ b/test/functional/services/common/browser.ts @@ -73,6 +73,11 @@ class BrowserService extends FtrService { return await this.driver.manage().window().getRect(); } + public async getWindowInnerSize(): Promise<{ height: number; width: number }> { + const JS_GET_INNER_WIDTH = 'return { width: window.innerWidth, height: window.innerHeight };'; + return await this.driver.executeScript(JS_GET_INNER_WIDTH); + } + /** * Sets the dimensions of a window. * https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_Window.html @@ -659,6 +664,12 @@ class BrowserService extends FtrService { this.log.error( `WebDriver session is no longer valid.\nProbably Chrome process crashed when it tried to use more memory than what was available.` ); + // TODO: Remove this after a while. We are enabling richer logs in order to try catch the real error cause. + this.log.error( + `Original Error Logging.\n Name: ${err.name};\n Message: ${err.message};\n Stack: ${ + err.stack + }\n RemoteStack: ${(err as NoSuchSessionError).remoteStacktrace}` + ); } return false; } diff --git a/test/functional/services/common/test_subjects.ts b/test/functional/services/common/test_subjects.ts index e54a1caa08d26..9cbce20b05068 100644 --- a/test/functional/services/common/test_subjects.ts +++ b/test/functional/services/common/test_subjects.ts @@ -285,9 +285,9 @@ export class TestSubjects extends FtrService { return await element.isEnabled(); } - public async isDisplayed(selector: string): Promise { + public async isDisplayed(selector: string, timeout?: number): Promise { this.log.debug(`TestSubjects.isDisplayed(${selector})`); - const element = await this.find(selector); + const element = await this.find(selector, timeout); return await element.isDisplayed(); } diff --git a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts index 92ad776e0c988..70df204b1de03 100644 --- a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts +++ b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts @@ -730,7 +730,32 @@ export class WebElementWrapper { } /** - * Scroll the element into view, avoiding the fixed header if necessary + * Scroll the element into view + * + * @param {ScrollIntoViewOptions} scrollIntoViewOptions + * @return {Promise} + */ + public scrollIntoView(scrollIntoViewOptions?: ScrollIntoViewOptions) { + return this.driver.executeScript( + (target: HTMLElement, options: ScrollIntoViewOptions) => target.scrollIntoView(options), + this._webElement, + scrollIntoViewOptions + ); + } + + /** + * Scroll the element into view if it is not already, avoiding the fixed header if necessary + * This method is a variation of the scrollIntoView method, where we only scroll into an element + * if it is not part of the "scrollable view". + * This implies a specific behavior, since the "scrollable view" of the view is identified by + * the `document.scrollingElement`, which always results to the html or body tag. + * + * Use cases: + * - An element (a section, a footer) is not visible in the whole page and we need to scroll into it. + * - An element is covered by the fixed header and we need to scroll into it ensuring is not covered. + * + * In case you have a scrollable list smaller that the size of the HTML document and you need + * to scroll into an element of that list, prefer using the `.scrollIntoView` method. * * @nonstandard * @return {Promise} diff --git a/test/plugin_functional/test_suites/core_plugins/applications.ts b/test/plugin_functional/test_suites/core_plugins/applications.ts index df4ac37b96464..5af71ba799457 100644 --- a/test/plugin_functional/test_suites/core_plugins/applications.ts +++ b/test/plugin_functional/test_suites/core_plugins/applications.ts @@ -49,11 +49,11 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide const navigateTo = async (path: string) => await browser.navigateTo(`${deployment.getHostPort()}${path}`); - // FLAKY: https://github.com/elastic/kibana/issues/127545 - describe.skip('ui applications', function describeIndexTests() { + describe('ui applications', function describeIndexTests() { before(async () => { await esArchiver.emptyKibanaIndex(); await PageObjects.common.navigateToApp('foo'); + await PageObjects.common.dismissBanner(); }); it('starts on home page', async () => { @@ -126,7 +126,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide expect(await testSubjects.exists('headerGlobalNav')).to.be(false); const wrapperHeight = await getAppWrapperHeight(); - const windowHeight = (await browser.getWindowSize()).height; + const windowHeight = (await browser.getWindowInnerSize()).height; expect(wrapperHeight).to.eql(windowHeight); }); @@ -136,7 +136,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide expect(await testSubjects.exists('headerGlobalNav')).to.be(true); const wrapperHeight = await getAppWrapperHeight(); - const windowHeight = (await browser.getWindowSize()).height; + const windowHeight = (await browser.getWindowInnerSize()).height; expect(wrapperHeight).to.be.below(windowHeight); }); }); diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index 6e0c4be2faaec..49951b9a3100a 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -145,6 +145,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'newsfeed.mainInterval (duration)', 'newsfeed.service.pathTemplate (string)', 'newsfeed.service.urlRoot (string)', + 'no_data_page.analyticsNoDataPageFlavor (any)', // It's a string (any because schema.conditional) 'telemetry.allowChangingOptInStatus (boolean)', 'telemetry.appendServerlessChannelsSuffix (any)', // It's a boolean (any because schema.conditional) 'telemetry.banner (boolean)', @@ -160,7 +161,8 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'telemetry.labels.testBuildId (string)', 'telemetry.labels.testJobId (string)', 'telemetry.labels.ciBuildName (string)', - 'telemetry.labels.serverless (any)', + 'telemetry.labels.performancePhase (string)', + 'telemetry.labels.serverless (any)', // It's the project type (string), claims any because schema.conditional. Can only be set on Serverless. 'telemetry.hidePrivacyStatement (boolean)', 'telemetry.optIn (boolean)', 'telemetry.sendUsageFrom (alternatives)', @@ -279,6 +281,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.securitySolution.prebuiltRulesPackageVersion (string)', 'xpack.snapshot_restore.slm_ui.enabled (boolean)', 'xpack.snapshot_restore.ui.enabled (boolean)', + 'xpack.stack_connectors.enableExperimental (array)', 'xpack.trigger_actions_ui.enableExperimental (array)', 'xpack.trigger_actions_ui.enableGeoTrackingThresholdAlert (boolean)', 'xpack.upgrade_assistant.featureSet.migrateSystemIndices (boolean)', @@ -291,10 +294,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.observability.unsafe.alertDetails.observability.enabled (boolean)', 'xpack.observability.unsafe.thresholdRule.enabled (boolean)', 'xpack.observability_onboarding.ui.enabled (boolean)', - /** - * xpack.discoverLogExplorer.featureFlags is conditional and will never resolve if used in non-serverless environment - */ - 'xpack.discoverLogExplorer.featureFlags.deepLinkVisible (any)', + 'xpack.observabilityLogExplorer.navigation.showAppLink (any)', // conditional, is actually a boolean ]; // We don't assert that actualExposedConfigKeys and expectedExposedConfigKeys are equal, because test failure messages with large // arrays are hard to grok. Instead, we take the difference between the two arrays and assert them separately, that way it's @@ -330,6 +330,30 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.security.showInsecureClusterWarning (boolean)', 'xpack.security.showNavLinks (boolean)', 'xpack.security.ui (any)', + + 'telemetry.allowChangingOptInStatus (boolean)', + 'telemetry.appendServerlessChannelsSuffix (any)', // It's a boolean (any because schema.conditional) + 'telemetry.banner (boolean)', + 'telemetry.labels.branch (string)', + 'telemetry.labels.ciBuildId (string)', + 'telemetry.labels.ciBuildJobId (string)', + 'telemetry.labels.ciBuildNumber (number)', + 'telemetry.labels.ftrConfig (string)', + 'telemetry.labels.gitRev (string)', + 'telemetry.labels.isPr (boolean)', + 'telemetry.labels.journeyName (string)', + 'telemetry.labels.prId (number)', + 'telemetry.labels.testBuildId (string)', + 'telemetry.labels.testJobId (string)', + 'telemetry.labels.ciBuildName (string)', + 'telemetry.labels.performancePhase (string)', + 'telemetry.labels.serverless (any)', // It's the project type (string), claims any because schema.conditional. Can only be set on Serverless. + 'telemetry.hidePrivacyStatement (boolean)', + 'telemetry.optIn (boolean)', + 'telemetry.sendUsageFrom (alternatives)', + 'telemetry.sendUsageTo (any)', + 'usageCollection.uiCounters.debug (boolean)', + 'usageCollection.uiCounters.enabled (boolean)', ]; // We don't assert that actualExposedConfigKeys and expectedExposedConfigKeys are equal, because test failure messages with large // arrays are hard to grok. Instead, we take the difference between the two arrays and assert them separately, that way it's diff --git a/test/plugin_functional/test_suites/saved_objects_management/hidden_types.ts b/test/plugin_functional/test_suites/saved_objects_management/hidden_types.ts index 439ece04e615f..8e7adb504ebee 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/hidden_types.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/hidden_types.ts @@ -21,8 +21,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide const esArchiver = getService('esArchiver'); const testSubjects = getService('testSubjects'); - // Failing: See https://github.com/elastic/kibana/issues/116059 - describe.skip('saved objects management with hidden types', () => { + describe('saved objects management with hidden types', () => { before(async () => { await esArchiver.load( 'test/functional/fixtures/es_archiver/saved_objects_management/hidden_types' diff --git a/tsconfig.base.json b/tsconfig.base.json index cf7d73b7a5a9c..afbbdcfe7601b 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -652,8 +652,6 @@ "@kbn/discover-customization-examples-plugin/*": ["examples/discover_customization_examples/*"], "@kbn/discover-enhanced-plugin": ["x-pack/plugins/discover_enhanced"], "@kbn/discover-enhanced-plugin/*": ["x-pack/plugins/discover_enhanced/*"], - "@kbn/discover-log-explorer-plugin": ["x-pack/plugins/discover_log_explorer"], - "@kbn/discover-log-explorer-plugin/*": ["x-pack/plugins/discover_log_explorer/*"], "@kbn/discover-plugin": ["src/plugins/discover"], "@kbn/discover-plugin/*": ["src/plugins/discover/*"], "@kbn/discover-utils": ["packages/kbn-discover-utils"], @@ -674,6 +672,8 @@ "@kbn/ecs-data-quality-dashboard-plugin/*": ["x-pack/plugins/ecs_data_quality_dashboard/*"], "@kbn/elastic-assistant": ["x-pack/packages/kbn-elastic-assistant"], "@kbn/elastic-assistant/*": ["x-pack/packages/kbn-elastic-assistant/*"], + "@kbn/elastic-assistant-plugin": ["x-pack/plugins/elastic_assistant"], + "@kbn/elastic-assistant-plugin/*": ["x-pack/plugins/elastic_assistant/*"], "@kbn/elasticsearch-client-plugin": ["test/plugin_functional/plugins/elasticsearch_client_plugin"], "@kbn/elasticsearch-client-plugin/*": ["test/plugin_functional/plugins/elasticsearch_client_plugin/*"], "@kbn/elasticsearch-client-xpack-plugin": ["x-pack/test/plugin_api_integration/plugins/elasticsearch_client"], @@ -936,6 +936,8 @@ "@kbn/locator-examples-plugin/*": ["examples/locator_examples/*"], "@kbn/locator-explorer-plugin": ["examples/locator_explorer"], "@kbn/locator-explorer-plugin/*": ["examples/locator_explorer/*"], + "@kbn/log-explorer-plugin": ["x-pack/plugins/log_explorer"], + "@kbn/log-explorer-plugin/*": ["x-pack/plugins/log_explorer/*"], "@kbn/logging": ["packages/kbn-logging"], "@kbn/logging/*": ["packages/kbn-logging/*"], "@kbn/logging-mocks": ["packages/kbn-logging-mocks"], @@ -1028,6 +1030,8 @@ "@kbn/newsfeed-plugin/*": ["src/plugins/newsfeed/*"], "@kbn/newsfeed-test-plugin": ["test/common/plugins/newsfeed"], "@kbn/newsfeed-test-plugin/*": ["test/common/plugins/newsfeed/*"], + "@kbn/no-data-page-plugin": ["src/plugins/no_data_page"], + "@kbn/no-data-page-plugin/*": ["src/plugins/no_data_page/*"], "@kbn/notifications-plugin": ["x-pack/plugins/notifications"], "@kbn/notifications-plugin/*": ["x-pack/plugins/notifications/*"], "@kbn/object-versioning": ["packages/kbn-object-versioning"], @@ -1038,6 +1042,8 @@ "@kbn/observability-alert-details/*": ["x-pack/packages/observability/alert_details/*"], "@kbn/observability-fixtures-plugin": ["x-pack/test/cases_api_integration/common/plugins/observability"], "@kbn/observability-fixtures-plugin/*": ["x-pack/test/cases_api_integration/common/plugins/observability/*"], + "@kbn/observability-log-explorer-plugin": ["x-pack/plugins/observability_log_explorer"], + "@kbn/observability-log-explorer-plugin/*": ["x-pack/plugins/observability_log_explorer/*"], "@kbn/observability-onboarding-plugin": ["x-pack/plugins/observability_onboarding"], "@kbn/observability-onboarding-plugin/*": ["x-pack/plugins/observability_onboarding/*"], "@kbn/observability-plugin": ["x-pack/plugins/observability"], @@ -1078,6 +1084,8 @@ "@kbn/preboot-example-plugin/*": ["examples/preboot_example/*"], "@kbn/presentation-util-plugin": ["src/plugins/presentation_util"], "@kbn/presentation-util-plugin/*": ["src/plugins/presentation_util/*"], + "@kbn/profiling-data-access-plugin": ["x-pack/plugins/profiling_data_access"], + "@kbn/profiling-data-access-plugin/*": ["x-pack/plugins/profiling_data_access/*"], "@kbn/profiling-plugin": ["x-pack/plugins/profiling"], "@kbn/profiling-plugin/*": ["x-pack/plugins/profiling/*"], "@kbn/random-sampling": ["x-pack/packages/kbn-random-sampling"], @@ -1190,6 +1198,8 @@ "@kbn/security-plugin/*": ["x-pack/plugins/security/*"], "@kbn/security-solution-ess": ["x-pack/plugins/security_solution_ess"], "@kbn/security-solution-ess/*": ["x-pack/plugins/security_solution_ess/*"], + "@kbn/security-solution-features": ["x-pack/packages/security-solution/features"], + "@kbn/security-solution-features/*": ["x-pack/packages/security-solution/features/*"], "@kbn/security-solution-fixtures-plugin": ["x-pack/test/cases_api_integration/common/plugins/security_solution"], "@kbn/security-solution-fixtures-plugin/*": ["x-pack/test/cases_api_integration/common/plugins/security_solution/*"], "@kbn/security-solution-navigation": ["x-pack/packages/security-solution/navigation"], @@ -1486,6 +1496,14 @@ "@kbn/ui-shared-deps-src/*": ["packages/kbn-ui-shared-deps-src/*"], "@kbn/ui-theme": ["packages/kbn-ui-theme"], "@kbn/ui-theme/*": ["packages/kbn-ui-theme/*"], + "@kbn/unified-data-table": ["packages/kbn-unified-data-table"], + "@kbn/unified-data-table/*": ["packages/kbn-unified-data-table/*"], + "@kbn/unified-doc-viewer": ["packages/kbn-unified-doc-viewer"], + "@kbn/unified-doc-viewer/*": ["packages/kbn-unified-doc-viewer/*"], + "@kbn/unified-doc-viewer-examples": ["examples/unified_doc_viewer"], + "@kbn/unified-doc-viewer-examples/*": ["examples/unified_doc_viewer/*"], + "@kbn/unified-doc-viewer-plugin": ["src/plugins/unified_doc_viewer"], + "@kbn/unified-doc-viewer-plugin/*": ["src/plugins/unified_doc_viewer/*"], "@kbn/unified-field-list": ["packages/kbn-unified-field-list"], "@kbn/unified-field-list/*": ["packages/kbn-unified-field-list/*"], "@kbn/unified-field-list-examples-plugin": ["examples/unified_field_list_examples"], @@ -1643,4 +1661,5 @@ "@kbn/ambient-storybook-types" ] } -} \ No newline at end of file +} + diff --git a/typings/index.d.ts b/typings/index.d.ts index 0134f5be84018..c7266d8fcccd7 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -22,3 +22,4 @@ declare module 'monaco-editor/esm/vs/basic-languages/css/css'; declare module 'monaco-editor/esm/vs/basic-languages/yaml/yaml'; declare module 'find-cypress-specs'; +declare module '@cypress/grep/src/plugin'; diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 3fa5a2da7c0ff..bcca0b5e14318 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -21,9 +21,9 @@ "xpack.customBranding": "plugins/custom_branding", "xpack.dashboard": "plugins/dashboard_enhanced", "xpack.discover": "plugins/discover_enhanced", - "xpack.discoverLogExplorer": "plugins/discover_log_explorer", "xpack.crossClusterReplication": "plugins/cross_cluster_replication", "xpack.elasticAssistant": "packages/kbn-elastic-assistant", + "xpack.ecsDataQualityDashboard": "plugins/ecs_data_quality_dashboard", "xpack.embeddableEnhanced": "plugins/embeddable_enhanced", "xpack.endpoint": "plugins/endpoint", "xpack.enterpriseSearch": "plugins/enterprise_search", @@ -38,6 +38,7 @@ "xpack.idxMgmt": "plugins/index_management", "xpack.indexLifecycleMgmt": "plugins/index_lifecycle_management", "xpack.infra": "plugins/infra", + "xpack.logExplorer": "plugins/log_explorer", "xpack.logsShared": "plugins/logs_shared", "xpack.fleet": "plugins/fleet", "xpack.ingestPipelines": "plugins/ingest_pipelines", @@ -60,6 +61,7 @@ ], "xpack.monitoring": ["plugins/monitoring"], "xpack.observability": "plugins/observability", + "xpack.observabilityLogExplorer": "plugins/observability_log_explorer", "xpack.observabilityShared": "plugins/observability_shared", "xpack.observability_onboarding": "plugins/observability_onboarding", "xpack.observabilityAiAssistant": "plugins/observability_ai_assistant", diff --git a/x-pack/packages/kbn-alerting-state-types/index.ts b/x-pack/packages/kbn-alerting-state-types/index.ts index c30ea9fb35f2a..80a5c3506eab8 100644 --- a/x-pack/packages/kbn-alerting-state-types/index.ts +++ b/x-pack/packages/kbn-alerting-state-types/index.ts @@ -5,20 +5,22 @@ * 2.0. */ -export type { - ThrottledActions, - LastScheduledActions, - AlertInstanceMeta, - AlertInstanceState, - AlertInstanceContext, - RawAlertInstance, -} from './src/alert_instance'; -export { rawAlertInstance } from './src/alert_instance'; - -export { DateFromString } from './src/date_from_string'; +export type { AlertInstanceContext } from './src/alert_instance'; export type { TrackedLifecycleAlertState, WrappedLifecycleRuleState } from './src/lifecycle_state'; export { wrappedStateRt } from './src/lifecycle_state'; -export type { RuleTaskState, RuleTaskParams } from './src/rule_task_instance'; -export { ActionsCompletion, ruleStateSchema, ruleParamsSchema } from './src/rule_task_instance'; +export type { RuleTaskParams } from './src/rule_task_instance'; +export { ActionsCompletion, ruleParamsSchema } from './src/rule_task_instance'; + +export type { + LatestTaskStateSchema as RuleTaskState, + MutableLatestTaskStateSchema as MutableRuleTaskState, + LatestRawAlertInstanceSchema as RawAlertInstance, + LatestAlertInstanceMetaSchema as AlertInstanceMeta, + MutableLatestAlertInstanceMetaSchema as MutableAlertInstanceMeta, + LatestAlertInstanceStateSchema as AlertInstanceState, + LatestThrottledActionSchema as ThrottledActions, + LatestLastScheduledActionsSchema as LastScheduledActions, +} from './src/task_state'; +export { stateSchemaByVersion, emptyState as emptyTaskState } from './src/task_state'; diff --git a/x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts b/x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts index 9685cdb656993..003fdcda742f9 100644 --- a/x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts +++ b/x-pack/packages/kbn-alerting-state-types/src/alert_instance.ts @@ -6,50 +6,6 @@ */ import * as t from 'io-ts'; -import { DateFromString } from './date_from_string'; - -const actionSchema = t.type({ - date: DateFromString, -}); - -export const throttledActionSchema = t.record(t.string, actionSchema); -export type ThrottledActions = t.TypeOf; - -const lastScheduledActionsSchema = t.intersection([ - t.partial({ - subgroup: t.string, - }), - t.type({ - group: t.string, - date: DateFromString, - }), - t.partial({ actions: throttledActionSchema }), -]); - -export type LastScheduledActions = t.TypeOf; - -const metaSchema = t.partial({ - lastScheduledActions: lastScheduledActionsSchema, - // an array used to track changes in alert state, the order is based on the rule executions (oldest to most recent) - // true - alert has changed from active/recovered - // false - the status has remained either active or recovered - flappingHistory: t.array(t.boolean), - // flapping flag that indicates whether the alert is flapping - flapping: t.boolean, - maintenanceWindowIds: t.array(t.string), - pendingRecoveredCount: t.number, - uuid: t.string, -}); -export type AlertInstanceMeta = t.TypeOf; - -const stateSchema = t.record(t.string, t.unknown); -export type AlertInstanceState = t.TypeOf; const contextSchema = t.record(t.string, t.unknown); export type AlertInstanceContext = t.TypeOf; - -export const rawAlertInstance = t.partial({ - state: stateSchema, - meta: metaSchema, -}); -export type RawAlertInstance = t.TypeOf; diff --git a/x-pack/packages/kbn-alerting-state-types/src/date_from_string.test.ts b/x-pack/packages/kbn-alerting-state-types/src/date_from_string.test.ts deleted file mode 100644 index eb63507630432..0000000000000 --- a/x-pack/packages/kbn-alerting-state-types/src/date_from_string.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { DateFromString } from './date_from_string'; -import { right, isLeft } from 'fp-ts/lib/Either'; - -describe('DateFromString', () => { - test('validated and parses a string into a Date', () => { - const date = new Date(1973, 10, 30); - expect(DateFromString.decode(date.toISOString())).toEqual(right(date)); - }); - - test('validated and returns a failure for an actual Date', () => { - const date = new Date(1973, 10, 30); - expect(isLeft(DateFromString.decode(date))).toEqual(true); - }); - - test('validated and returns a failure for an invalid Date string', () => { - expect(isLeft(DateFromString.decode('1234-23-45'))).toEqual(true); - }); - - test('validated and returns a failure for a null value', () => { - expect(isLeft(DateFromString.decode(null))).toEqual(true); - }); -}); diff --git a/x-pack/packages/kbn-alerting-state-types/src/date_from_string.ts b/x-pack/packages/kbn-alerting-state-types/src/date_from_string.ts deleted file mode 100644 index 1588334a44d49..0000000000000 --- a/x-pack/packages/kbn-alerting-state-types/src/date_from_string.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; -import { either } from 'fp-ts/lib/Either'; - -// represents a Date from an ISO string -export const DateFromString = new t.Type( - 'DateFromString', - // detect the type - (value): value is Date => value instanceof Date, - (valueToDecode, context) => - either.chain( - // validate this is a string - t.string.validate(valueToDecode, context), - // decode - (value) => { - const decoded = new Date(value); - return isNaN(decoded.getTime()) ? t.failure(valueToDecode, context) : t.success(decoded); - } - ), - (valueToEncode) => valueToEncode.toISOString() -); diff --git a/x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts b/x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts index 415b5e665cec5..a5b881f6f124c 100644 --- a/x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts +++ b/x-pack/packages/kbn-alerting-state-types/src/rule_task_instance.ts @@ -6,27 +6,12 @@ */ import * as t from 'io-ts'; -import { throttledActionSchema, rawAlertInstance } from './alert_instance'; -import { DateFromString } from './date_from_string'; export enum ActionsCompletion { COMPLETE = 'complete', PARTIAL = 'partial', } -export const ruleStateSchema = t.partial({ - alertTypeState: t.record(t.string, t.unknown), - // tracks the active alerts - alertInstances: t.record(t.string, rawAlertInstance), - // tracks the recovered alerts for flapping purposes - alertRecoveredInstances: t.record(t.string, rawAlertInstance), - previousStartedAt: t.union([t.null, DateFromString]), - summaryActions: throttledActionSchema, -}); - -// This is serialized in the rule task document -export type RuleTaskState = t.TypeOf; - export const ruleParamsSchema = t.intersection([ t.type({ alertId: t.string, diff --git a/x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts b/x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts new file mode 100644 index 0000000000000..dbceac9534ae7 --- /dev/null +++ b/x-pack/packages/kbn-alerting-state-types/src/task_state/index.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { type TypeOf } from '@kbn/config-schema'; +import * as v1 from './v1'; + +export const stateSchemaByVersion = { + 1: v1.versionDefinition, +}; + +const latest = v1; +/** + * WARNING: Do not modify the code below when doing a new version. + * Update the "latest" variable instead. + */ +const latestTaskStateSchema = latest.versionDefinition.schema; +export type LatestTaskStateSchema = TypeOf; +export type LatestRawAlertInstanceSchema = TypeOf; +export type LatestAlertInstanceMetaSchema = TypeOf; +export type LatestAlertInstanceStateSchema = TypeOf; +export type LatestThrottledActionSchema = TypeOf; +export type LatestLastScheduledActionsSchema = TypeOf; + +export const emptyState: LatestTaskStateSchema = { + alertTypeState: {}, + alertInstances: {}, + alertRecoveredInstances: {}, + previousStartedAt: null, + summaryActions: {}, +}; + +type Mutable = { + -readonly [k in keyof T]: Mutable; +}; +export type MutableLatestTaskStateSchema = Mutable; +export type MutableLatestAlertInstanceMetaSchema = Mutable; diff --git a/x-pack/packages/kbn-alerting-state-types/src/task_state/lib/index.ts b/x-pack/packages/kbn-alerting-state-types/src/task_state/lib/index.ts new file mode 100644 index 0000000000000..219705c1185b4 --- /dev/null +++ b/x-pack/packages/kbn-alerting-state-types/src/task_state/lib/index.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 { isPlainObject } from 'lodash'; + +export function isJSONObject(obj: unknown): obj is Record { + return isPlainObject(obj); +} + +export function isString(value: unknown): value is string { + return typeof value === 'string'; +} + +export function isBoolean(value: unknown): value is boolean { + return typeof value === 'boolean'; +} + +export function isNumber(value: unknown): value is number { + return typeof value === 'number'; +} + +export function isStringArray(value: unknown): value is string[] { + return Array.isArray(value) && value.every((item) => typeof item === 'string'); +} + +export function isBooleanArray(value: unknown): value is boolean[] { + return Array.isArray(value) && value.every((item) => typeof item === 'boolean'); +} diff --git a/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/index.ts b/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/index.ts new file mode 100644 index 0000000000000..4b28d7e68d085 --- /dev/null +++ b/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { upMigration } from './migration'; +import { versionSchema } from './schema'; + +export { + versionSchema, + throttledActionSchema, + rawAlertInstanceSchema, + metaSchema, + alertStateSchema, + lastScheduledActionsSchema, +} from './schema'; + +export const versionDefinition = { + up: upMigration, + schema: versionSchema, +}; diff --git a/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/migration.test.ts b/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/migration.test.ts new file mode 100644 index 0000000000000..fab82accc9a30 --- /dev/null +++ b/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/migration.test.ts @@ -0,0 +1,225 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + migrateThrottledActions, + migrateLastScheduledActions, + migrateMeta, + migrateAlertInstances, + upMigration, +} from './migration'; + +describe('migrateThrottledActions', () => { + it('should return undefined if input is not an object', () => { + const result = migrateThrottledActions(null); + expect(result).toBeUndefined(); + }); + + it('should return the migrated throttledActions object', () => { + const input = { + key1: { date: '2023-07-31T12:00:00Z' }, + key2: { date: '2023-07-30T12:00:00Z' }, + key3: 'notAnObject', + }; + + const expectedOutput = { + key1: { date: '2023-07-31T12:00:00Z' }, + key2: { date: '2023-07-30T12:00:00Z' }, + }; + + const result = migrateThrottledActions(input); + expect(result).toEqual(expectedOutput); + }); +}); + +describe('migrateLastScheduledActions', () => { + it('should return undefined if input is not a valid lastScheduledActions object', () => { + const result = migrateLastScheduledActions({ group: 'group1' }); // Missing 'date' property + expect(result).toBeUndefined(); + }); + + it('should return the migrated lastScheduledActions object', () => { + const input = { + group: 'group1', + subgroup: 'subgroup1', + date: '2023-07-31T12:00:00Z', + actions: { + key1: { date: '2023-07-31T12:00:00Z' }, + key2: { date: '2023-07-30T12:00:00Z' }, + }, + }; + + const expectedOutput = { + group: 'group1', + subgroup: 'subgroup1', + date: '2023-07-31T12:00:00Z', + actions: { + key1: { date: '2023-07-31T12:00:00Z' }, + key2: { date: '2023-07-30T12:00:00Z' }, + }, + }; + + const result = migrateLastScheduledActions(input); + expect(result).toEqual(expectedOutput); + }); +}); + +describe('migrateMeta', () => { + it('should return undefined if input is not an object', () => { + const result = migrateMeta(null); + expect(result).toBeUndefined(); + }); + + it('should return the migrated meta object', () => { + const input = { + lastScheduledActions: { + group: 'group1', + date: '2023-07-31T12:00:00Z', + }, + flappingHistory: [true, false, true], + flapping: true, + maintenanceWindowIds: ['id1', 'id2'], + pendingRecoveredCount: 3, + uuid: 'abc123', + }; + + const expectedOutput = { + lastScheduledActions: { + group: 'group1', + date: '2023-07-31T12:00:00Z', + }, + flappingHistory: [true, false, true], + flapping: true, + maintenanceWindowIds: ['id1', 'id2'], + pendingRecoveredCount: 3, + uuid: 'abc123', + }; + + const result = migrateMeta(input); + expect(result).toEqual(expectedOutput); + }); +}); + +describe('migrateAlertInstances', () => { + it('should return undefined if input is not an object', () => { + const result = migrateAlertInstances(null); + expect(result).toBeUndefined(); + }); + + it('should return the migrated alertInstances object', () => { + const input = { + instance1: { + meta: { + lastScheduledActions: { + group: 'group1', + date: '2023-07-31T12:00:00Z', + }, + flappingHistory: [true, false, true], + flapping: true, + maintenanceWindowIds: ['id1', 'id2'], + pendingRecoveredCount: 3, + uuid: 'abc123', + }, + state: { key: 'value' }, + }, + instance2: { + meta: { + lastScheduledActions: { + group: 'group2', + date: '2023-07-30T12:00:00Z', + }, + }, + }, + instance3: 'notAnObject', + }; + + const expectedOutput = { + instance1: { + meta: { + lastScheduledActions: { + group: 'group1', + date: '2023-07-31T12:00:00Z', + }, + flappingHistory: [true, false, true], + flapping: true, + maintenanceWindowIds: ['id1', 'id2'], + pendingRecoveredCount: 3, + uuid: 'abc123', + }, + state: { key: 'value' }, + }, + instance2: { + meta: { + lastScheduledActions: { + group: 'group2', + date: '2023-07-30T12:00:00Z', + }, + }, + }, + }; + + const result = migrateAlertInstances(input); + expect(result).toEqual(expectedOutput); + }); +}); + +describe('upMigration', () => { + it('should return the migrated state object', () => { + const inputState = { + alertTypeState: {}, + alertInstances: { + instance1: { + meta: { + lastScheduledActions: { + group: 'group1', + date: '2023-07-31T12:00:00Z', + }, + flappingHistory: [true, false, true], + flapping: true, + maintenanceWindowIds: ['id1', 'id2'], + pendingRecoveredCount: 3, + uuid: 'abc123', + }, + state: { key: 'value' }, + }, + }, + alertRecoveredInstances: {}, + previousStartedAt: '2023-07-30T12:00:00Z', + summaryActions: { + action1: { date: '2023-07-31T12:00:00Z' }, + }, + }; + + const expectedOutput = { + alertTypeState: {}, + alertInstances: { + instance1: { + meta: { + lastScheduledActions: { + group: 'group1', + date: '2023-07-31T12:00:00Z', + }, + flappingHistory: [true, false, true], + flapping: true, + maintenanceWindowIds: ['id1', 'id2'], + pendingRecoveredCount: 3, + uuid: 'abc123', + }, + state: { key: 'value' }, + }, + }, + alertRecoveredInstances: {}, + previousStartedAt: '2023-07-30T12:00:00Z', + summaryActions: { + action1: { date: '2023-07-31T12:00:00Z' }, + }, + }; + + const result = upMigration(inputState); + expect(result).toEqual(expectedOutput); + }); +}); diff --git a/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/migration.ts b/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/migration.ts new file mode 100644 index 0000000000000..d4e4947bcb0b8 --- /dev/null +++ b/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/migration.ts @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { type TypeOf } from '@kbn/config-schema'; +import { isJSONObject, isString, isBoolean, isNumber, isStringArray, isBooleanArray } from '../lib'; +import { + versionSchema, + throttledActionSchema, + rawAlertInstanceSchema, + metaSchema, + lastScheduledActionsSchema, +} from './schema'; + +type VersionSchema = TypeOf; +type ThrottledActionsSchema = TypeOf; +type LastScheduledActionsSchema = TypeOf; +type RawAlertInstanceSchema = TypeOf; + +export function migrateThrottledActions( + throttledActions: unknown +): ThrottledActionsSchema | undefined { + if (!isJSONObject(throttledActions)) { + return; + } + return Object.keys(throttledActions).reduce((acc, key) => { + const val = throttledActions[key]; + if (isJSONObject(val) && isString(val.date)) { + acc[key] = { + date: val.date, + }; + } + return acc; + }, {} as TypeOf); +} + +export function migrateLastScheduledActions( + lastScheduledActions: unknown +): LastScheduledActionsSchema | undefined { + if ( + !isJSONObject(lastScheduledActions) || + !isString(lastScheduledActions.group) || + !isString(lastScheduledActions.date) + ) { + return; + } + return { + subgroup: isString(lastScheduledActions.subgroup) ? lastScheduledActions.subgroup : undefined, + group: lastScheduledActions.group, + date: lastScheduledActions.date, + actions: migrateThrottledActions(lastScheduledActions.actions), + }; +} + +export function migrateMeta(meta: unknown): TypeOf | undefined { + if (!isJSONObject(meta)) { + return; + } + return { + lastScheduledActions: migrateLastScheduledActions(meta.lastScheduledActions), + flappingHistory: isBooleanArray(meta.flappingHistory) ? meta.flappingHistory : undefined, + flapping: isBoolean(meta.flapping) ? meta.flapping : undefined, + maintenanceWindowIds: isStringArray(meta.maintenanceWindowIds) + ? meta.maintenanceWindowIds + : undefined, + pendingRecoveredCount: isNumber(meta.pendingRecoveredCount) + ? meta.pendingRecoveredCount + : undefined, + uuid: isString(meta.uuid) ? meta.uuid : undefined, + }; +} + +export function migrateAlertInstances( + alertInstances: unknown +): Record | undefined { + if (!isJSONObject(alertInstances)) { + return; + } + return Object.keys(alertInstances).reduce((acc, key) => { + const val = alertInstances[key]; + if (isJSONObject(val)) { + acc[key] = { + meta: migrateMeta(val.meta), + state: isJSONObject(val.state) ? val.state : undefined, + }; + } + return acc; + }, {} as Record); +} + +export const upMigration = (state: Record): VersionSchema => { + return { + alertTypeState: isJSONObject(state.alertTypeState) ? state.alertTypeState : undefined, + alertInstances: migrateAlertInstances(state.alertInstances), + alertRecoveredInstances: migrateAlertInstances(state.alertRecoveredInstances), + previousStartedAt: isString(state.previousStartedAt) ? state.previousStartedAt : undefined, + summaryActions: migrateThrottledActions(state.summaryActions), + }; +}; diff --git a/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/schema.ts b/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/schema.ts new file mode 100644 index 0000000000000..62e802483dcf7 --- /dev/null +++ b/x-pack/packages/kbn-alerting-state-types/src/task_state/v1/schema.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 { schema } from '@kbn/config-schema'; + +const actionSchema = schema.object({ date: schema.string() }); +export const throttledActionSchema = schema.recordOf(schema.string(), actionSchema); +// TODO: Add schema by rule type for alert state +// https://github.com/elastic/kibana/issues/159344 +export const alertStateSchema = schema.recordOf(schema.string(), schema.maybe(schema.any())); +// TODO: Add schema by rule type for rule state +// https://github.com/elastic/kibana/issues/159344 +const ruleStateSchema = schema.recordOf(schema.string(), schema.maybe(schema.any())); + +export const lastScheduledActionsSchema = schema.object({ + subgroup: schema.maybe(schema.string()), + group: schema.string(), + date: schema.string(), + actions: schema.maybe(throttledActionSchema), +}); + +export const metaSchema = schema.object({ + lastScheduledActions: schema.maybe(lastScheduledActionsSchema), + // an array used to track changes in alert state, the order is based on the rule executions (oldest to most recent) + // true - alert has changed from active/recovered + // false - the status has remained either active or recovered + flappingHistory: schema.maybe(schema.arrayOf(schema.boolean())), + // flapping flag that indicates whether the alert is flapping + flapping: schema.maybe(schema.boolean()), + maintenanceWindowIds: schema.maybe(schema.arrayOf(schema.string())), + pendingRecoveredCount: schema.maybe(schema.number()), + uuid: schema.maybe(schema.string()), +}); + +export const rawAlertInstanceSchema = schema.object({ + meta: schema.maybe(metaSchema), + state: schema.maybe(alertStateSchema), +}); + +export const versionSchema = schema.object({ + alertTypeState: schema.maybe(ruleStateSchema), + // tracks the active alerts + alertInstances: schema.maybe(schema.recordOf(schema.string(), rawAlertInstanceSchema)), + // tracks the recovered alerts for flapping purposes + alertRecoveredInstances: schema.maybe(schema.recordOf(schema.string(), rawAlertInstanceSchema)), + previousStartedAt: schema.maybe(schema.nullable(schema.string())), + summaryActions: schema.maybe(throttledActionSchema), +}); diff --git a/x-pack/packages/kbn-alerting-state-types/tsconfig.json b/x-pack/packages/kbn-alerting-state-types/tsconfig.json index 6d27b06d5f8ba..e1a705d2a1ed8 100644 --- a/x-pack/packages/kbn-alerting-state-types/tsconfig.json +++ b/x-pack/packages/kbn-alerting-state-types/tsconfig.json @@ -13,5 +13,5 @@ "exclude": [ "target/**/*" ], - "kbn_references": [] + "kbn_references": ["@kbn/config-schema"] } diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.test.tsx new file mode 100644 index 0000000000000..65b8183b60a0b --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.test.tsx @@ -0,0 +1,129 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { HttpSetup } from '@kbn/core-http-browser'; +import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/public/common'; + +import { fetchConnectorExecuteAction, FetchConnectorExecuteAction } from './api'; +import type { Conversation, Message } from '../assistant_context/types'; +import { API_ERROR } from './translations'; + +jest.mock('@kbn/core-http-browser'); + +const mockHttp = { + fetch: jest.fn(), +} as unknown as HttpSetup; + +const apiConfig: Conversation['apiConfig'] = { + connectorId: 'foo', + model: 'gpt-4', + provider: OpenAiProviderType.OpenAi, +}; + +const messages: Message[] = [ + { content: 'This is a test', role: 'user', timestamp: new Date().toLocaleString() }, +]; + +describe('fetchConnectorExecuteAction', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('calls the internal assistant API when assistantLangChain is true', async () => { + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: true, + http: mockHttp, + messages, + apiConfig, + }; + + await fetchConnectorExecuteAction(testProps); + + expect(mockHttp.fetch).toHaveBeenCalledWith( + '/internal/elastic_assistant/actions/connector/foo/_execute', + { + body: '{"params":{"subActionParams":{"body":"{\\"model\\":\\"gpt-4\\",\\"messages\\":[{\\"role\\":\\"user\\",\\"content\\":\\"This is a test\\"}],\\"n\\":1,\\"stop\\":null,\\"temperature\\":0.2}"},"subAction":"test"}}', + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + signal: undefined, + } + ); + }); + + it('calls the actions connector api when assistantLangChain is false', async () => { + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: false, + http: mockHttp, + messages, + apiConfig, + }; + + await fetchConnectorExecuteAction(testProps); + + expect(mockHttp.fetch).toHaveBeenCalledWith('/api/actions/connector/foo/_execute', { + body: '{"params":{"subActionParams":{"body":"{\\"model\\":\\"gpt-4\\",\\"messages\\":[{\\"role\\":\\"user\\",\\"content\\":\\"This is a test\\"}],\\"n\\":1,\\"stop\\":null,\\"temperature\\":0.2}"},"subAction":"test"}}', + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + signal: undefined, + }); + }); + + it('returns API_ERROR when the response status is not ok', async () => { + (mockHttp.fetch as jest.Mock).mockResolvedValue({ status: 'error' }); + + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: false, + http: mockHttp, + messages, + apiConfig, + }; + + const result = await fetchConnectorExecuteAction(testProps); + + expect(result).toBe(API_ERROR); + }); + + it('returns API_ERROR when there are no choices', async () => { + (mockHttp.fetch as jest.Mock).mockResolvedValue({ status: 'ok', data: {} }); + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: false, + http: mockHttp, + messages, + apiConfig, + }; + + const result = await fetchConnectorExecuteAction(testProps); + + expect(result).toBe(API_ERROR); + }); + + it('return the trimmed first `choices` `message` `content` when the API call is successful', async () => { + (mockHttp.fetch as jest.Mock).mockResolvedValue({ + status: 'ok', + data: { + choices: [ + { + message: { + content: ' Test response ', // leading and trailing whitespace + }, + }, + ], + }, + }); + + const testProps: FetchConnectorExecuteAction = { + assistantLangChain: false, + http: mockHttp, + messages, + apiConfig, + }; + + const result = await fetchConnectorExecuteAction(testProps); + + expect(result).toBe('Test response'); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.tsx index 0bb68409caf91..c8624e365419d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api.tsx @@ -14,6 +14,7 @@ import { API_ERROR } from './translations'; import { MODEL_GPT_3_5_TURBO } from '../connectorland/models/model_selector/model_selector'; export interface FetchConnectorExecuteAction { + assistantLangChain: boolean; apiConfig: Conversation['apiConfig']; http: HttpSetup; messages: Message[]; @@ -21,6 +22,7 @@ export interface FetchConnectorExecuteAction { } export const fetchConnectorExecuteAction = async ({ + assistantLangChain, http, messages, apiConfig, @@ -54,19 +56,20 @@ export const fetchConnectorExecuteAction = async ({ }; try { + const path = assistantLangChain + ? `/internal/elastic_assistant/actions/connector/${apiConfig?.connectorId}/_execute` + : `/api/actions/connector/${apiConfig?.connectorId}/_execute`; + // TODO: Find return type for this API // eslint-disable-next-line @typescript-eslint/no-explicit-any - const response = await http.fetch( - `/api/actions/connector/${apiConfig?.connectorId}/_execute`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(requestBody), - signal, - } - ); + const response = await http.fetch(path, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody), + signal, + }); const data = response.data; if (response.status !== 'ok') { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_avatar/assistant_avatar.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_avatar/assistant_avatar.tsx new file mode 100644 index 0000000000000..20b378447b7b8 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_avatar/assistant_avatar.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, { ReactNode } from 'react'; + +export interface AssistantAvatarProps { + size?: keyof typeof sizeMap; + // Required for EuiAvatar `iconType` prop + // eslint-disable-next-line react/no-unused-prop-types + children?: ReactNode; +} + +export const sizeMap = { + xl: 64, + l: 48, + m: 32, + s: 24, + xs: 16, +}; + +/** + * Default Elastic AI Assistant logo + * + * TODO: Can be removed once added to EUI + */ +export const AssistantAvatar = ({ size = 's' }: AssistantAvatarProps) => ( + + + + + + +); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx index 59dbbd9105487..a4c0e2fe20719 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx @@ -13,10 +13,7 @@ import { alertConvo, emptyWelcomeConvo } from '../../mock/conversation'; const testProps = { currentConversation: emptyWelcomeConvo, - currentTitle: { - title: 'Test Title', - titleIcon: 'logoSecurity', - }, + title: 'Test Title', docLinks: { ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', DOC_LINK_VERSION: 'master', diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx index 2070368aadd59..65c3c267e9a8e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx @@ -26,7 +26,6 @@ import * as i18n from '../translations'; interface OwnProps { currentConversation: Conversation; - currentTitle: { title: string | JSX.Element; titleIcon: string }; defaultConnectorId?: string; defaultProvider?: OpenAiProviderType; docLinks: Omit; @@ -39,6 +38,7 @@ interface OwnProps { setSelectedConversationId: React.Dispatch>; shouldDisableKeyboardShortcut?: () => boolean; showAnonymizedValues: boolean; + title: string | JSX.Element; } type Props = OwnProps; @@ -49,7 +49,6 @@ type Props = OwnProps; */ export const AssistantHeader: React.FC = ({ currentConversation, - currentTitle, defaultConnectorId, defaultProvider, docLinks, @@ -62,6 +61,7 @@ export const AssistantHeader: React.FC = ({ setSelectedConversationId, shouldDisableKeyboardShortcut, showAnonymizedValues, + title, }) => { const showAnonymizedValuesChecked = useMemo( () => @@ -81,10 +81,10 @@ export const AssistantHeader: React.FC = ({ > diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.test.tsx index e24d8fe48291b..bdc9f71e42fc5 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.test.tsx @@ -12,20 +12,18 @@ import { TestProviders } from '../../mock/test_providers/test_providers'; const testProps = { title: 'Test Title', - titleIcon: 'globe', docLinks: { ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', DOC_LINK_VERSION: '7.15' }, selectedConversation: undefined, }; describe('AssistantTitle', () => { it('the component renders correctly with valid props', () => { - const { getByText, container } = render( + const { getByText } = render( ); expect(getByText('Test Title')).toBeInTheDocument(); - expect(container.querySelector('[data-euiicon-type="globe"]')).not.toBeNull(); }); it('clicking on the popover button opens the popover with the correct link', () => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx index 33fc1644a5dca..ccf04c38f5c93 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx @@ -10,7 +10,6 @@ import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, - EuiIcon, EuiLink, EuiModalHeaderTitle, EuiPopover, @@ -19,22 +18,21 @@ import { } from '@elastic/eui'; import type { DocLinksStart } from '@kbn/core-doc-links-browser'; import { FormattedMessage } from '@kbn/i18n-react'; -import { css } from '@emotion/react'; import * as i18n from '../translations'; import type { Conversation } from '../../..'; import { ConnectorSelectorInline } from '../../connectorland/connector_selector_inline/connector_selector_inline'; +import { AssistantAvatar } from '../assistant_avatar/assistant_avatar'; /** - * Renders a header title with an icon, a tooltip button, and a popover with + * Renders a header title, a tooltip button, and a popover with * information about the assistant feature and access to documentation. */ export const AssistantTitle: React.FC<{ isDisabled?: boolean; title: string | JSX.Element; - titleIcon: string; docLinks: Omit; selectedConversation: Conversation | undefined; -}> = ({ isDisabled = false, title, titleIcon, docLinks, selectedConversation }) => { +}> = ({ isDisabled = false, title, docLinks, selectedConversation }) => { const selectedConnectorId = selectedConversation?.apiConfig?.connectorId; const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = docLinks; @@ -58,7 +56,7 @@ export const AssistantTitle: React.FC<{ const content = useMemo( () => ( - - + + @@ -106,7 +99,6 @@ export const AssistantTitle: React.FC<{ anchorPosition="rightUp" > -

    {i18n.TOOLTIP_TITLE}

    {content}

    @@ -119,7 +111,6 @@ export const AssistantTitle: React.FC<{ {}} - onConnectorSelectionChange={() => {}} selectedConnectorId={selectedConnectorId} selectedConversation={selectedConversation} /> diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx index 853501da409c1..a0c8226b3ea7e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/conversations/conversation_settings/conversation_settings.tsx @@ -23,6 +23,8 @@ import { ModelSelector } from '../../../connectorland/models/model_selector/mode import { UseAssistantContext } from '../../../assistant_context'; import { ConversationSelectorSettings } from '../conversation_selector_settings'; import { getDefaultSystemPrompt } from '../../use_conversation/helpers'; +import { useLoadConnectors } from '../../../connectorland/use_load_connectors'; +import { getGenAiConfig } from '../../../connectorland/helpers'; export interface ConversationSettingsProps { actionTypeRegistry: ActionTypeRegistryContract; @@ -63,6 +65,8 @@ export const ConversationSettings: React.FC = React.m return getDefaultSystemPrompt({ allSystemPrompts, conversation: selectedConversation }); }, [allSystemPrompts, selectedConversation]); + const { data: connectors, isSuccess: areConnectorsFetched } = useLoadConnectors({ http }); + // Conversation callbacks // When top level conversation selection changes const onConversationSelectionChange = useCallback( @@ -131,10 +135,13 @@ export const ConversationSettings: React.FC = React.m [selectedConversation, setUpdatedConversationSettings] ); - const selectedConnectorId = useMemo( - () => selectedConversation?.apiConfig.connectorId, - [selectedConversation?.apiConfig.connectorId] - ); + const selectedConnector = useMemo(() => { + const selectedConnectorId = selectedConversation?.apiConfig.connectorId; + if (areConnectorsFetched) { + return connectors?.find((c) => c.id === selectedConnectorId); + } + return undefined; + }, [areConnectorsFetched, connectors, selectedConversation?.apiConfig.connectorId]); const selectedProvider = useMemo( () => selectedConversation?.apiConfig.provider, @@ -142,16 +149,19 @@ export const ConversationSettings: React.FC = React.m ); const handleOnConnectorSelectionChange = useCallback( - (connectorId: string, provider: OpenAiProviderType) => { + (connector) => { if (selectedConversation != null) { + const config = getGenAiConfig(connector); + setUpdatedConversationSettings((prev) => ({ ...prev, [selectedConversation.id]: { ...selectedConversation, apiConfig: { ...selectedConversation.apiConfig, - connectorId, - provider, + connectorId: connector?.id, + provider: config?.apiProvider, + model: config?.defaultModel, }, }, })); @@ -160,10 +170,11 @@ export const ConversationSettings: React.FC = React.m [selectedConversation, setUpdatedConversationSettings] ); - const selectedModel = useMemo( - () => selectedConversation?.apiConfig.model, - [selectedConversation?.apiConfig.model] - ); + const selectedModel = useMemo(() => { + const connectorModel = getGenAiConfig(selectedConnector)?.defaultModel; + // Prefer conversation configuration over connector default + return selectedConversation?.apiConfig.model ?? connectorModel; + }, [selectedConnector, selectedConversation?.apiConfig.model]); const handleOnModelSelectionChange = useCallback( (model?: string) => { @@ -244,23 +255,24 @@ export const ConversationSettings: React.FC = React.m isDisabled={selectedConversation == null} onConnectorModalVisibilityChange={() => {}} onConnectorSelectionChange={handleOnConnectorSelectionChange} - selectedConnectorId={selectedConnectorId} + selectedConnectorId={selectedConnector?.id} /> - {selectedProvider === OpenAiProviderType.OpenAi && ( - - - - )} + {selectedConnector?.isPreconfigured === false && + selectedProvider === OpenAiProviderType.OpenAi && ( + + + + )} ); } diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx index 26af65e60dfff..4ea1ed240870d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx @@ -172,13 +172,8 @@ const AssistantComponent: React.FC = ({ }, }); - const currentTitle: { title: string | JSX.Element; titleIcon: string } = - isWelcomeSetup && blockBotConversation.theme?.title && blockBotConversation.theme?.titleIcon - ? { - title: blockBotConversation.theme?.title, - titleIcon: blockBotConversation.theme?.titleIcon, - } - : { title, titleIcon: 'logoSecurity' }; + const currentTitle: string | JSX.Element = + isWelcomeSetup && blockBotConversation.theme?.title ? blockBotConversation.theme?.title : title; const bottomRef = useRef(null); const lastCommentRef = useRef(null); @@ -426,7 +421,6 @@ const AssistantComponent: React.FC = ({ {showTitle && ( = ({ setIsSettingsModalVisible={setIsSettingsModalVisible} setSelectedConversationId={setSelectedConversationId} showAnonymizedValues={showAnonymizedValues} + title={currentTitle} /> )} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/translations.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/translations.ts index 580e02247e3ee..7afa89f8f4ab6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/translations.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/translations.ts @@ -41,13 +41,6 @@ export const API_ERROR = i18n.translate('xpack.elasticAssistant.assistant.apiErr 'An error occurred sending your message. If the problem persists, please test the connector configuration.', }); -export const TOOLTIP_TITLE = i18n.translate( - 'xpack.elasticAssistant.assistant.technicalPreview.tooltipTitle', - { - defaultMessage: 'Beta', - } -); - export const TOOLTIP_ARIA_LABEL = i18n.translate( 'xpack.elasticAssistant.documentationLinks.ariaLabel', { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_send_messages/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_send_messages/index.tsx index 3a3b72c253862..c68d82d99b9ac 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_send_messages/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_send_messages/index.tsx @@ -8,6 +8,8 @@ import { useCallback, useState } from 'react'; import { HttpSetup } from '@kbn/core-http-browser'; + +import { useAssistantContext } from '../../assistant_context'; import { Conversation, Message } from '../../assistant_context/types'; import { fetchConnectorExecuteAction } from '../api'; @@ -23,20 +25,25 @@ interface UseSendMessages { } export const useSendMessages = (): UseSendMessages => { + const { assistantLangChain } = useAssistantContext(); const [isLoading, setIsLoading] = useState(false); - const sendMessages = useCallback(async ({ apiConfig, http, messages }: SendMessagesProps) => { - setIsLoading(true); - try { - return await fetchConnectorExecuteAction({ - http, - messages, - apiConfig, - }); - } finally { - setIsLoading(false); - } - }, []); + const sendMessages = useCallback( + async ({ apiConfig, http, messages }: SendMessagesProps) => { + setIsLoading(true); + try { + return await fetchConnectorExecuteAction({ + assistantLangChain, + http, + messages, + apiConfig, + }); + } finally { + setIsLoading(false); + } + }, + [assistantLangChain] + ); return { isLoading, sendMessages }; }; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.test.tsx index 466ccbb83cb0f..6e39da055043a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/index.test.tsx @@ -28,6 +28,7 @@ const ContextWrapper: React.FC = ({ children }) => ( CodeBlockDetails[][]; baseAllow: string[]; @@ -85,6 +86,7 @@ export interface UseAssistantContext { augmentMessageCodeBlocks: (currentConversation: Conversation) => CodeBlockDetails[][]; allQuickPrompts: QuickPrompt[]; allSystemPrompts: Prompt[]; + assistantLangChain: boolean; baseAllow: string[]; baseAllowReplacement: string[]; docLinks: Omit; @@ -129,6 +131,7 @@ const AssistantContext = React.createContext(un export const AssistantProvider: React.FC = ({ actionTypeRegistry, assistantAvailability, + assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, @@ -248,6 +251,7 @@ export const AssistantProvider: React.FC = ({ () => ({ actionTypeRegistry, assistantAvailability, + assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, allQuickPrompts: localStorageQuickPrompts ?? [], @@ -284,6 +288,7 @@ export const AssistantProvider: React.FC = ({ [ actionTypeRegistry, assistantAvailability, + assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx index f1a03329657b6..df3f0b54cd14f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector/index.tsx @@ -14,31 +14,24 @@ import { } from '@kbn/triggers-actions-ui-plugin/public'; import { HttpSetup } from '@kbn/core-http-browser'; -import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types'; import { ConnectorAddModal } from '@kbn/triggers-actions-ui-plugin/public/common/constants'; -import { - GEN_AI_CONNECTOR_ID, - OpenAiProviderType, -} from '@kbn/stack-connectors-plugin/public/common'; +import { GEN_AI_CONNECTOR_ID } from '@kbn/stack-connectors-plugin/public/common'; import { useLoadConnectors } from '../use_load_connectors'; import * as i18n from '../translations'; import { useLoadActionTypes } from '../use_load_action_types'; import { useAssistantContext } from '../../assistant_context'; +import { getGenAiConfig } from '../helpers'; export const ADD_NEW_CONNECTOR = 'ADD_NEW_CONNECTOR'; interface Props { actionTypeRegistry: ActionTypeRegistryContract; http: HttpSetup; isDisabled?: boolean; - onConnectorSelectionChange: (connectorId: string, provider: OpenAiProviderType) => void; + onConnectorSelectionChange: (connector: ActionConnector | undefined) => void; selectedConnectorId?: string; onConnectorModalVisibilityChange?: (isVisible: boolean) => void; } -interface Config { - apiProvider: string; -} - export const ConnectorSelector: React.FC = React.memo( ({ actionTypeRegistry, @@ -95,18 +88,19 @@ export const ConnectorSelector: React.FC = React.memo( const connectorOptions = useMemo(() => { return ( connectors?.map((connector) => { - const apiProvider: string | undefined = ( - connector as ActionConnectorProps - )?.config?.apiProvider; + const apiProvider = getGenAiConfig(connector)?.apiProvider; + const connectorDetails = connector.isPreconfigured + ? i18n.PRECONFIGURED_CONNECTOR + : apiProvider; return { value: connector.id, inputDisplay: connector.name, dropdownDisplay: ( {connector.name} - {apiProvider && ( - -

    {apiProvider}

    + {connectorDetails && ( + +

    {connectorDetails}

    )}
    @@ -138,10 +132,8 @@ export const ConnectorSelector: React.FC = React.memo( return; } - const apiProvider = ( - connectors?.find((c) => c.id === connectorId) as ActionConnectorProps - )?.config.apiProvider as OpenAiProviderType; - onConnectorSelectionChange(connectorId, apiProvider); + const connector = connectors?.find((c) => c.id === connectorId); + onConnectorSelectionChange(connector); }, [connectors, onConnectorSelectionChange, onConnectorModalVisibilityChange] ); @@ -162,12 +154,8 @@ export const ConnectorSelector: React.FC = React.memo( { - onConnectorSelectionChange( - savedAction.id, - (savedAction as ActionConnectorProps)?.config - .apiProvider as OpenAiProviderType - ); + postSaveEventHandler={(connector: ActionConnector) => { + onConnectorSelectionChange(connector); refetchConnectors?.(); cleanupAndCloseModal(); }} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.test.tsx index 774098eba8b2e..3b1ff0be86181 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.test.tsx @@ -65,7 +65,6 @@ describe('ConnectorSelectorInline', () => { @@ -85,7 +84,6 @@ describe('ConnectorSelectorInline', () => { @@ -105,7 +103,6 @@ describe('ConnectorSelectorInline', () => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.tsx index 66d7971731deb..d7f4a50f90ae9 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/connector_selector_inline.tsx @@ -10,7 +10,6 @@ import React, { useCallback, useMemo, useState } from 'react'; import { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public'; -import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types'; import { ConnectorAddModal } from '@kbn/triggers-actions-ui-plugin/public/common/constants'; import { GEN_AI_CONNECTOR_ID, @@ -23,20 +22,16 @@ import * as i18n from '../translations'; import { useLoadActionTypes } from '../use_load_action_types'; import { useAssistantContext } from '../../assistant_context'; import { useConversation } from '../../assistant/use_conversation'; +import { getGenAiConfig } from '../helpers'; export const ADD_NEW_CONNECTOR = 'ADD_NEW_CONNECTOR'; interface Props { isDisabled?: boolean; - onConnectorSelectionChange: (connectorId: string, provider: OpenAiProviderType) => void; selectedConnectorId?: string; selectedConversation?: Conversation; onConnectorModalVisibilityChange?: (isVisible: boolean) => void; } -interface Config { - apiProvider: string; -} - const inputContainerClassName = css` height: 32px; @@ -82,7 +77,6 @@ export const ConnectorSelectorInline: React.FC = React.memo( onConnectorModalVisibilityChange, selectedConnectorId, selectedConversation, - onConnectorSelectionChange, }) => { const [isOpen, setIsOpen] = useState(false); const { actionTypeRegistry, assistantAvailability, http } = useAssistantContext(); @@ -136,9 +130,10 @@ export const ConnectorSelectorInline: React.FC = React.memo( const connectorOptions = useMemo(() => { return ( connectors?.map((connector) => { - const apiProvider: string | undefined = ( - connector as ActionConnectorProps - )?.config?.apiProvider; + const apiProvider = getGenAiConfig(connector)?.apiProvider; + const connectorDetails = connector.isPreconfigured + ? i18n.PRECONFIGURED_CONNECTOR + : apiProvider; return { value: connector.id, inputDisplay: ( @@ -149,9 +144,9 @@ export const ConnectorSelectorInline: React.FC = React.memo( dropdownDisplay: ( {connector.name} - {apiProvider && ( + {connectorDetails && ( -

    {apiProvider}

    +

    {connectorDetails}

    )}
    @@ -182,7 +177,7 @@ export const ConnectorSelectorInline: React.FC = React.memo( const handleOnBlur = useCallback(() => setIsOpen(false), []); const onChange = useCallback( - (connectorId: string, apiProvider?: OpenAiProviderType) => { + (connectorId: string, apiProvider?: OpenAiProviderType, model?: string) => { setIsOpen(false); if (connectorId === ADD_NEW_CONNECTOR) { @@ -191,31 +186,22 @@ export const ConnectorSelectorInline: React.FC = React.memo( return; } - const provider = - apiProvider ?? - ((connectors?.find((c) => c.id === connectorId) as ActionConnectorProps) - ?.config.apiProvider as OpenAiProviderType); - + const connector = connectors?.find((c) => c.id === connectorId); + const config = getGenAiConfig(connector); if (selectedConversation != null) { setApiConfig({ conversationId: selectedConversation.id, apiConfig: { ...selectedConversation.apiConfig, connectorId, - provider, + // With the inline component, prefer config args to handle 'new connector' case + provider: apiProvider ?? config?.apiProvider, + model: model ?? config?.defaultModel, }, }); } - - onConnectorSelectionChange(connectorId, provider); }, - [ - connectors, - selectedConversation, - onConnectorSelectionChange, - onConnectorModalVisibilityChange, - setApiConfig, - ] + [connectors, selectedConversation, onConnectorModalVisibilityChange, setApiConfig] ); const placeholderComponent = useMemo( @@ -276,11 +262,9 @@ export const ConnectorSelectorInline: React.FC = React.memo( { - const provider = (savedAction as ActionConnectorProps)?.config - .apiProvider as OpenAiProviderType; - onChange(savedAction.id, provider); - onConnectorSelectionChange(savedAction.id, provider); + postSaveEventHandler={(connector: ActionConnector) => { + const config = getGenAiConfig(connector); + onChange(connector.id, config?.apiProvider, config?.defaultModel); refetchConnectors?.(); cleanupAndCloseModal(); }} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx index d8923bfb8b7f2..9429ad9435ea7 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_setup/index.tsx @@ -14,11 +14,7 @@ import { ConnectorAddModal } from '@kbn/triggers-actions-ui-plugin/public/common import type { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public'; import { ActionType } from '@kbn/triggers-actions-ui-plugin/public'; -import { - GEN_AI_CONNECTOR_ID, - OpenAiProviderType, -} from '@kbn/stack-connectors-plugin/public/common'; -import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types'; +import { GEN_AI_CONNECTOR_ID } from '@kbn/stack-connectors-plugin/public/common'; import { WELCOME_CONVERSATION } from '../../assistant/use_conversation/sample_conversations'; import { Conversation, Message } from '../../..'; import { useLoadActionTypes } from '../use_load_action_types'; @@ -29,6 +25,8 @@ import { clearPresentationData, conversationHasNoPresentationData } from './help import * as i18n from '../translations'; import { useAssistantContext } from '../../assistant_context'; import { useLoadConnectors } from '../use_load_connectors'; +import { AssistantAvatar } from '../../assistant/assistant_avatar/assistant_avatar'; +import { getGenAiConfig } from '../helpers'; const ConnectorButtonWrapper = styled.div` margin-bottom: 10px; @@ -38,10 +36,6 @@ const SkipEuiText = styled(EuiText)` margin-top: 20px; `; -interface Config { - apiProvider: string; -} - export interface ConnectorSetupProps { conversation?: Conversation; onSetupComplete?: () => void; @@ -186,21 +180,14 @@ export const useConnectorSetup = ({ name={i18n.CONNECTOR_SETUP_USER_ASSISTANT} size="l" color="subdued" - iconType={conversation?.theme?.assistant?.icon ?? 'logoElastic'} + iconType={AssistantAvatar} /> ), timestamp: `${i18n.CONNECTOR_SETUP_TIMESTAMP_AT}: ${message.timestamp}`, }; return commentProps; }), - [ - assistantName, - commentBody, - conversation.messages, - conversation?.theme?.assistant?.icon, - currentMessageIndex, - userName, - ] + [assistantName, commentBody, conversation.messages, currentMessageIndex, userName] ); return { @@ -229,16 +216,17 @@ export const useConnectorSetup = ({ setIsConnectorModalVisible(false)} - postSaveEventHandler={(savedAction: ActionConnector) => { + postSaveEventHandler={(connector: ActionConnector) => { + const config = getGenAiConfig(connector); // Add connector to all conversations Object.values(conversations).forEach((c) => { setApiConfig({ conversationId: c.id, apiConfig: { ...c.apiConfig, - connectorId: savedAction.id, - provider: (savedAction as ActionConnectorProps)?.config - .apiProvider as OpenAiProviderType, + connectorId: connector.id, + provider: config?.apiProvider, + model: config?.defaultModel, }, }); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/helpers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/helpers.tsx new file mode 100644 index 0000000000000..ffd9604ab328f --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/helpers.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 type { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public'; +import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types'; +import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/gen_ai/constants'; + +interface GenAiConfig { + apiProvider?: OpenAiProviderType; + apiUrl?: string; + defaultModel?: string; +} + +/** + * Returns the GenAiConfig for a given ActionConnector. Note that if the connector is preconfigured, + * the config will be undefined as the connector is neither available nor editable. + * + * TODO: Extract and use separate types from GenAiConfig from '@kbn/stack-connectors-plugin/common/gen_ai/types' + * + * @param connector + */ +export const getGenAiConfig = (connector: ActionConnector | undefined): GenAiConfig | undefined => { + if (!connector?.isPreconfigured) { + return (connector as ActionConnectorProps)?.config; + } + return undefined; +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/translations.ts b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/translations.ts index dbc692d6b5493..ae84527b21c7d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/translations.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/translations.ts @@ -31,6 +31,13 @@ export const WELCOME_SECURITY = i18n.translate( } ); +export const PRECONFIGURED_CONNECTOR = i18n.translate( + 'xpack.elasticAssistant.assistant.connectors.preconfiguredTitle', + { + defaultMessage: 'Preconfigured', + } +); + export const CONNECTOR_SELECTOR_TITLE = i18n.translate( 'xpack.elasticAssistant.assistant.connectors.connectorSelector.ariaLabel', { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx b/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx index aec3a6262ba4c..484dd316cc0ac 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/mock/test_providers/test_providers.tsx @@ -66,6 +66,7 @@ export const TestProvidersComponent: React.FC = ({ void; + baseTheme: Theme; canUserCreateAndReadCases: () => boolean; + endDate?: string | null; formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; getGroupByFieldsOnClick: ( @@ -53,8 +56,8 @@ export interface Props { patternIndexNames: Record; patternRollups: Record; patterns: string[]; + startDate?: string | null; theme?: PartialTheme; - baseTheme: Theme; updatePatternIndexNames: ({ indexNames, pattern, @@ -68,6 +71,7 @@ export interface Props { const DataQualityDetailsComponent: React.FC = ({ addSuccessToast, canUserCreateAndReadCases, + endDate, formatBytes, formatNumber, getGroupByFieldsOnClick, @@ -77,18 +81,20 @@ const DataQualityDetailsComponent: React.FC = ({ patternIndexNames, patternRollups, patterns, + startDate, theme, baseTheme, updatePatternIndexNames, updatePatternRollup, }) => { + const { isILMAvailable } = useDataQualityContext(); const [selectedIndex, setSelectedIndex] = useState(null); const onIndexSelected = useCallback(async ({ indexName, pattern }: SelectedIndex) => { setSelectedIndex({ indexName, pattern }); }, []); - if (ilmPhases.length === 0) { + if (isILMAvailable && ilmPhases.length === 0) { return ; } @@ -107,6 +113,7 @@ const DataQualityDetailsComponent: React.FC = ({ = ({ patternRollups={patternRollups} selectedIndex={selectedIndex} setSelectedIndex={setSelectedIndex} + startDate={startDate} updatePatternIndexNames={updatePatternIndexNames} updatePatternRollup={updatePatternRollup} /> diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/indices_details/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/indices_details/index.tsx index bc481503cd2bf..3bfbe9065ebea 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/indices_details/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/indices_details/index.tsx @@ -24,6 +24,7 @@ import { PatternRollup, SelectedIndex } from '../../../../types'; export interface Props { addSuccessToast: (toast: { title: string }) => void; canUserCreateAndReadCases: () => boolean; + endDate?: string | null; formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; getGroupByFieldsOnClick: ( @@ -53,6 +54,7 @@ export interface Props { patterns: string[]; selectedIndex: SelectedIndex | null; setSelectedIndex: (selectedIndex: SelectedIndex | null) => void; + startDate?: string | null; theme?: PartialTheme; baseTheme: Theme; updatePatternIndexNames: ({ @@ -68,6 +70,7 @@ export interface Props { const IndicesDetailsComponent: React.FC = ({ addSuccessToast, canUserCreateAndReadCases, + endDate, formatBytes, formatNumber, getGroupByFieldsOnClick, @@ -79,6 +82,7 @@ const IndicesDetailsComponent: React.FC = ({ patterns, selectedIndex, setSelectedIndex, + startDate, theme, baseTheme, updatePatternIndexNames, @@ -90,6 +94,7 @@ const IndicesDetailsComponent: React.FC = ({ = ({ patternRollup={patternRollups[pattern]} selectedIndex={selectedIndex} setSelectedIndex={setSelectedIndex} + startDate={startDate} theme={theme} baseTheme={baseTheme} updatePatternIndexNames={updatePatternIndexNames} diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/helpers.test.ts index 45e8f1ba1b4ad..ce085a53e8557 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/helpers.test.ts @@ -102,6 +102,7 @@ describe('helpers', () => { const pattern = 'auditbeat-*'; const flattenedBuckets = getFlattenedBuckets({ ilmPhases, + isILMAvailable: true, patternRollups, }); @@ -129,12 +130,45 @@ describe('helpers', () => { }, ]); }); + + test('it returns the expected legend items when isILMAvailable is false', () => { + const pattern = 'auditbeat-*'; + const flattenedBuckets = getFlattenedBuckets({ + ilmPhases, + isILMAvailable: false, + patternRollups, + }); + expect(getLegendItemsForPattern({ pattern, flattenedBuckets })).toEqual([ + { + color: euiThemeVars.euiColorSuccess, + ilmPhase: null, + index: '.ds-auditbeat-8.6.1-2023.02.07-000001', + pattern: 'auditbeat-*', + sizeInBytes: 18791790, + }, + { + color: euiThemeVars.euiColorDanger, + ilmPhase: null, + index: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 28409, + }, + { + color: euiThemeVars.euiColorDanger, + ilmPhase: null, + index: 'auditbeat-custom-empty-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 247, + }, + ]); + }); }); describe('getLegendItems', () => { test('it returns the expected legend items', () => { const flattenedBuckets = getFlattenedBuckets({ ilmPhases, + isILMAvailable: true, patternRollups, }); @@ -205,6 +239,7 @@ describe('helpers', () => { expect( getFlattenedBuckets({ ilmPhases, + isILMAvailable: true, patternRollups, }) ).toEqual([ @@ -250,6 +285,57 @@ describe('helpers', () => { }, ]); }); + + test('it returns the expected flattened buckets when isILMAvailable is false', () => { + expect( + getFlattenedBuckets({ + ilmPhases, + isILMAvailable: false, + patternRollups, + }) + ).toEqual([ + { + ilmPhase: undefined, + incompatible: 0, + indexName: '.internal.alerts-security.alerts-default-000001', + pattern: '.alerts-security.alerts-default', + sizeInBytes: 0, + }, + { + ilmPhase: undefined, + incompatible: 0, + indexName: '.ds-auditbeat-8.6.1-2023.02.07-000001', + pattern: 'auditbeat-*', + sizeInBytes: 18791790, + }, + { + ilmPhase: undefined, + incompatible: 1, + indexName: 'auditbeat-custom-empty-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 247, + }, + { + ilmPhase: undefined, + incompatible: 3, + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 28409, + }, + { + ilmPhase: undefined, + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'packetbeat-*', + sizeInBytes: 512194751, + }, + { + ilmPhase: undefined, + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'packetbeat-*', + sizeInBytes: 584326147, + }, + ]); + }); }); describe('getFillColor', () => { @@ -276,6 +362,7 @@ describe('helpers', () => { test('it returns the expected map', () => { const flattenedBuckets = getFlattenedBuckets({ ilmPhases, + isILMAvailable: true, patternRollups, }); @@ -363,6 +450,7 @@ describe('helpers', () => { const layer0FillColor = 'transparent'; const flattenedBuckets = getFlattenedBuckets({ ilmPhases, + isILMAvailable: true, patternRollups, }); const pathToFlattenedBucketMap = getPathToFlattenedBucketMap(flattenedBuckets); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/helpers.ts index 09ed53402a89f..326488e707aa9 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/helpers.ts @@ -98,9 +98,11 @@ export const getLegendItems = ({ export const getFlattenedBuckets = ({ ilmPhases, + isILMAvailable, patternRollups, }: { ilmPhases: string[]; + isILMAvailable: boolean; patternRollups: Record; }): FlattenedBucket[] => Object.values(patternRollups).reduce((acc, patternRollup) => { @@ -111,13 +113,15 @@ export const getFlattenedBuckets = ({ ); const { ilmExplain, pattern, results, stats } = patternRollup; - if (ilmExplain != null && stats != null) { + if (((isILMAvailable && ilmExplain != null) || !isILMAvailable) && stats != null) { return [ ...acc, ...Object.entries(stats).reduce( (validStats, [indexName, indexStats]) => { - const ilmPhase = getIlmPhase(ilmExplain[indexName]); - const isSelectedPhase = ilmPhase != null && ilmPhasesMap[ilmPhase] != null; + const ilmPhase = getIlmPhase(ilmExplain?.[indexName], isILMAvailable); + const isSelectedPhase = + (isILMAvailable && ilmPhase != null && ilmPhasesMap[ilmPhase] != null) || + !isILMAvailable; if (isSelectedPhase) { const incompatible = diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/index.tsx index 2fe51e7d9acd4..571bc6329920e 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/storage_details/index.tsx @@ -12,6 +12,7 @@ import { getFlattenedBuckets } from './helpers'; import { StorageTreemap } from '../../../storage_treemap'; import { DEFAULT_MAX_CHART_HEIGHT, StorageTreemapContainer } from '../../../tabs/styles'; import { PatternRollup, SelectedIndex } from '../../../../types'; +import { useDataQualityContext } from '../../../data_quality_context'; export interface Props { formatBytes: (value: number | undefined) => string; @@ -32,13 +33,16 @@ const StorageDetailsComponent: React.FC = ({ theme, baseTheme, }) => { + const { isILMAvailable } = useDataQualityContext(); + const flattenedBuckets = useMemo( () => getFlattenedBuckets({ ilmPhases, + isILMAvailable, patternRollups, }), - [ilmPhases, patternRollups] + [ilmPhases, isILMAvailable, patternRollups] ); return ( diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/index.tsx index e21bfd19b66ce..c36e34fc803e2 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/index.tsx @@ -24,7 +24,9 @@ import { useResultsRollup } from '../../use_results_rollup'; interface Props { addSuccessToast: (toast: { title: string }) => void; + baseTheme: Theme; canUserCreateAndReadCases: () => boolean; + endDate?: string | null; formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; getGroupByFieldsOnClick: ( @@ -52,13 +54,14 @@ interface Props { }) => void; patterns: string[]; setLastChecked: (lastChecked: string) => void; + startDate?: string | null; theme?: PartialTheme; - baseTheme: Theme; } const BodyComponent: React.FC = ({ addSuccessToast, canUserCreateAndReadCases, + endDate, formatBytes, formatNumber, getGroupByFieldsOnClick, @@ -68,6 +71,7 @@ const BodyComponent: React.FC = ({ openCreateCaseFlyout, patterns, setLastChecked, + startDate, theme, baseTheme, }) => { @@ -115,7 +119,9 @@ const BodyComponent: React.FC = ({ = ({ patterns={patterns} patternIndexNames={patternIndexNames} patternRollups={patternRollups} + startDate={startDate} theme={theme} - baseTheme={baseTheme} updatePatternIndexNames={updatePatternIndexNames} updatePatternRollup={updatePatternRollup} /> diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_context/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_context/index.test.tsx index 1628705efb78a..26843c67ff64e 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_context/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_context/index.test.tsx @@ -18,7 +18,11 @@ const mockTelemetryEvents = { reportDataQualityCheckAllCompleted: mockReportDataQualityCheckAllClicked, }; const ContextWrapper: React.FC = ({ children }) => ( - + {children} ); @@ -52,4 +56,11 @@ describe('DataQualityContext', () => { expect(telemetryEvents).toEqual(mockTelemetryEvents); }); + + test('it should return the isILMAvailable param', async () => { + const { result } = renderHook(useDataQualityContext, { wrapper: ContextWrapper }); + const isILMAvailable = await result.current.isILMAvailable; + + expect(isILMAvailable).toEqual(true); + }); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_context/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_context/index.tsx index 8456c89068829..4f5c883ddd696 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_context/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_context/index.tsx @@ -11,6 +11,7 @@ import { TelemetryEvents } from '../../types'; interface DataQualityProviderProps { httpFetch: HttpHandler; + isILMAvailable: boolean; telemetryEvents: TelemetryEvents; } @@ -19,14 +20,16 @@ const DataQualityContext = React.createContext = ({ children, httpFetch, + isILMAvailable, telemetryEvents, }) => { const value = useMemo( () => ({ httpFetch, + isILMAvailable, telemetryEvents, }), - [httpFetch, telemetryEvents] + [httpFetch, isILMAvailable, telemetryEvents] ); return {children}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_summary/summary_actions/check_all/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_summary/summary_actions/check_all/index.test.tsx index 236e7dc3eb9bd..fbf0be3354a53 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_summary/summary_actions/check_all/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_summary/summary_actions/check_all/index.test.tsx @@ -139,6 +139,48 @@ describe('CheckAll', () => { expect(screen.getByTestId('checkAll')).toHaveTextContent(CHECK_ALL); }); + test('it renders a disabled button when ILM available and ilmPhases is an empty array', () => { + render( + + + + ); + + expect(screen.getByTestId('checkAll').hasAttribute('disabled')).toBeTruthy(); + }); + + test('it renders the expected button when ILM is NOT available', () => { + render( + + + + ); + + expect(screen.getByTestId('checkAll').hasAttribute('disabled')).toBeFalsy(); + }); + test('it renders the expected button text when a check is running', () => { render( diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_summary/summary_actions/check_all/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_summary/summary_actions/check_all/index.tsx index 9f43af65bb0dd..3801fabcb374a 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_summary/summary_actions/check_all/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/data_quality_summary/summary_actions/check_all/index.tsx @@ -60,7 +60,7 @@ const CheckAllComponent: React.FC = ({ setCheckAllTotalIndiciesToCheck, setIndexToCheck, }) => { - const { httpFetch } = useDataQualityContext(); + const { httpFetch, isILMAvailable } = useDataQualityContext(); const abortController = useRef(new AbortController()); const [isRunning, setIsRunning] = useState(false); @@ -157,7 +157,7 @@ const CheckAllComponent: React.FC = ({ }; }, [abortController]); - const disabled = ilmPhases.length === 0; + const disabled = isILMAvailable && ilmPhases.length === 0; return ( theme.eui.euiSizeS}; @@ -45,11 +46,13 @@ export const getResultsSortedByDocsCount = ( export const getAllMarkdownCommentsFromResults = ({ formatBytes, formatNumber, + isILMAvailable, patternIndexNames, patternRollup, }: { formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; + isILMAvailable: boolean; patternIndexNames: Record; patternRollup: PatternRollup; }): string[] => { @@ -59,6 +62,7 @@ export const getAllMarkdownCommentsFromResults = ({ const summaryTableItems = getSummaryTableItems({ ilmExplain: patternRollup.ilmExplain, indexNames: patternIndexNames[patternRollup.pattern] ?? [], + isILMAvailable, pattern: patternRollup.pattern, patternDocsCount: patternRollup.docsCount ?? 0, results: patternRollup.results, @@ -78,6 +82,7 @@ export const getAllMarkdownCommentsFromResults = ({ ilmPhase: item.ilmPhase, indexName: item.indexName, incompatible: result?.incompatible, + isILMAvailable, patternDocsCount: patternRollup.docsCount ?? 0, sizeInBytes: getSizeInBytes({ indexName: item.indexName, stats: patternRollup.stats }), }).trim(); @@ -85,7 +90,7 @@ export const getAllMarkdownCommentsFromResults = ({ const initialComments: string[] = summaryTableMarkdownRows.length > 0 - ? [getSummaryTableMarkdownHeader(), ...summaryTableMarkdownRows] + ? [getSummaryTableMarkdownHeader(isILMAvailable), ...summaryTableMarkdownRows] : []; return sortedResults.reduce( @@ -97,11 +102,13 @@ export const getAllMarkdownCommentsFromResults = ({ export const getAllMarkdownComments = ({ formatBytes, formatNumber, + isILMAvailable, patternIndexNames, patternRollups, }: { formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; + isILMAvailable: boolean; patternIndexNames: Record; patternRollups: Record; }): string[] => { @@ -123,6 +130,7 @@ export const getAllMarkdownComments = ({ ...getAllMarkdownCommentsFromResults({ formatBytes, formatNumber, + isILMAvailable, patternRollup: patternRollups[pattern], patternIndexNames, }), @@ -178,6 +186,7 @@ const SummaryActionsComponent: React.FC = ({ totalIndicesChecked, sizeInBytes, }) => { + const { isILMAvailable } = useDataQualityContext(); const [indexToCheck, setIndexToCheck] = useState(null); const [checkAllIndiciesChecked, setCheckAllIndiciesChecked] = useState(0); const [checkAllTotalIndiciesToCheck, setCheckAllTotalIndiciesToCheck] = useState(0); @@ -199,6 +208,7 @@ const SummaryActionsComponent: React.FC = ({ ...getAllMarkdownComments({ formatBytes, formatNumber, + isILMAvailable, patternIndexNames, patternRollups, }), @@ -213,6 +223,7 @@ const SummaryActionsComponent: React.FC = ({ errorSummary, formatBytes, formatNumber, + isILMAvailable, patternIndexNames, patternRollups, sizeInBytes, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/index.tsx index 1fc0789af6e53..9d1ef9b67e4e8 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/index.tsx @@ -103,7 +103,7 @@ const IndexPropertiesComponent: React.FC = ({ updatePatternRollup, }) => { const { error: mappingsError, indexes, loading: loadingMappings } = useMappings(indexName); - const { telemetryEvents } = useDataQualityContext(); + const { telemetryEvents, isILMAvailable } = useDataQualityContext(); const requestItems = useMemo( () => @@ -236,6 +236,7 @@ const IndexPropertiesComponent: React.FC = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount: patternRollup.docsCount ?? 0, sizeInBytes: patternRollup.sizeInBytes, @@ -290,6 +291,7 @@ const IndexPropertiesComponent: React.FC = ({ ilmPhase, indexId, indexName, + isILMAvailable, loadingMappings, loadingUnallowedValues, mappingsError, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.test.ts index b51a49ecc89df..05523a1c43d03 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.test.ts @@ -423,10 +423,18 @@ describe('helpers', () => { describe('getSummaryTableMarkdownHeader', () => { test('it returns the expected header', () => { - expect(getSummaryTableMarkdownHeader()).toEqual( + const isILMAvailable = true; + expect(getSummaryTableMarkdownHeader(isILMAvailable)).toEqual( '| Result | Index | Docs | Incompatible fields | ILM Phase | Size |\n|--------|-------|------|---------------------|-----------|------|' ); }); + + test('it returns the expected header when isILMAvailable is false', () => { + const isILMAvailable = false; + expect(getSummaryTableMarkdownHeader(isILMAvailable)).toEqual( + '| Result | Index | Docs | Incompatible fields | Size |\n|--------|-------|------|---------------------|------|' + ); + }); }); describe('getSummaryTableMarkdownRow', () => { @@ -438,6 +446,7 @@ describe('helpers', () => { formatNumber, incompatible: 3, ilmPhase: 'unmanaged', + isILMAvailable: true, indexName: 'auditbeat-custom-index-1', patternDocsCount: 57410, sizeInBytes: 28413, @@ -454,11 +463,28 @@ describe('helpers', () => { incompatible: undefined, // <-- ilmPhase: undefined, // <-- indexName: 'auditbeat-custom-index-1', + isILMAvailable: true, patternDocsCount: 57410, sizeInBytes: 28413, }) ).toEqual('| -- | auditbeat-custom-index-1 | 4 (0.0%) | -- | -- | 27.7KB |\n'); }); + + test('it returns the expected row when isILMAvailable is false', () => { + expect( + getSummaryTableMarkdownRow({ + docsCount: 4, + formatBytes, + formatNumber, + incompatible: undefined, // <-- + ilmPhase: undefined, // <-- + indexName: 'auditbeat-custom-index-1', + isILMAvailable: false, + patternDocsCount: 57410, + sizeInBytes: 28413, + }) + ).toEqual('| -- | auditbeat-custom-index-1 | 4 (0.0%) | -- | 27.7KB |\n'); + }); }); describe('getSummaryTableMarkdownComment', () => { @@ -470,6 +496,7 @@ describe('helpers', () => { formatNumber, ilmPhase: 'unmanaged', indexName: 'auditbeat-custom-index-1', + isILMAvailable: true, partitionedFieldMetadata: mockPartitionedFieldMetadata, patternDocsCount: 57410, sizeInBytes: 28413, @@ -478,6 +505,24 @@ describe('helpers', () => { '| Result | Index | Docs | Incompatible fields | ILM Phase | Size |\n|--------|-------|------|---------------------|-----------|------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 | `unmanaged` | 27.7KB |\n\n' ); }); + + test('it returns the expected comment when isILMAvailable is false', () => { + expect( + getSummaryTableMarkdownComment({ + docsCount: 4, + formatBytes, + formatNumber, + ilmPhase: 'unmanaged', + indexName: 'auditbeat-custom-index-1', + isILMAvailable: false, + partitionedFieldMetadata: mockPartitionedFieldMetadata, + patternDocsCount: 57410, + sizeInBytes: 28413, + }) + ).toEqual( + '| Result | Index | Docs | Incompatible fields | Size |\n|--------|-------|------|---------------------|------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 | 27.7KB |\n\n' + ); + }); }); describe('getStatsRollupMarkdownComment', () => { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.ts index 32424dff66883..6f92374e2555d 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.ts @@ -216,13 +216,18 @@ export const getResultEmoji = (incompatible: number | undefined): string => { } }; -export const getSummaryTableMarkdownHeader = (): string => - `| ${RESULT} | ${INDEX} | ${DOCS} | ${INCOMPATIBLE_FIELDS} | ${ILM_PHASE} | ${SIZE} | +export const getSummaryTableMarkdownHeader = (isILMAvailable: boolean): string => + isILMAvailable + ? `| ${RESULT} | ${INDEX} | ${DOCS} | ${INCOMPATIBLE_FIELDS} | ${ILM_PHASE} | ${SIZE} | |${getHeaderSeparator(RESULT)}|${getHeaderSeparator(INDEX)}|${getHeaderSeparator( - DOCS - )}|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|${getHeaderSeparator( - ILM_PHASE - )}|${getHeaderSeparator(SIZE)}|`; + DOCS + )}|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|${getHeaderSeparator( + ILM_PHASE + )}|${getHeaderSeparator(SIZE)}|` + : `| ${RESULT} | ${INDEX} | ${DOCS} | ${INCOMPATIBLE_FIELDS} | ${SIZE} | +|${getHeaderSeparator(RESULT)}|${getHeaderSeparator(INDEX)}|${getHeaderSeparator( + DOCS + )}|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|${getHeaderSeparator(SIZE)}|`; export const getSummaryTableMarkdownRow = ({ docsCount, @@ -231,6 +236,7 @@ export const getSummaryTableMarkdownRow = ({ ilmPhase, incompatible, indexName, + isILMAvailable, patternDocsCount, sizeInBytes, }: { @@ -240,17 +246,26 @@ export const getSummaryTableMarkdownRow = ({ ilmPhase: IlmPhase | undefined; incompatible: number | undefined; indexName: string; + isILMAvailable: boolean; patternDocsCount: number; sizeInBytes: number | undefined; }): string => - `| ${getResultEmoji(incompatible)} | ${escape(indexName)} | ${formatNumber( - docsCount - )} (${getDocsCountPercent({ - docsCount, - patternDocsCount, - })}) | ${incompatible ?? EMPTY_PLACEHOLDER} | ${ - ilmPhase != null ? getCodeFormattedValue(ilmPhase) : EMPTY_PLACEHOLDER - } | ${formatBytes(sizeInBytes)} | + isILMAvailable + ? `| ${getResultEmoji(incompatible)} | ${escape(indexName)} | ${formatNumber( + docsCount + )} (${getDocsCountPercent({ + docsCount, + patternDocsCount, + })}) | ${incompatible ?? EMPTY_PLACEHOLDER} | ${ + ilmPhase != null ? getCodeFormattedValue(ilmPhase) : EMPTY_PLACEHOLDER + } | ${formatBytes(sizeInBytes)} | +` + : `| ${getResultEmoji(incompatible)} | ${escape(indexName)} | ${formatNumber( + docsCount + )} (${getDocsCountPercent({ + docsCount, + patternDocsCount, + })}) | ${incompatible ?? EMPTY_PLACEHOLDER} | ${formatBytes(sizeInBytes)} | `; export const getSummaryTableMarkdownComment = ({ @@ -259,6 +274,7 @@ export const getSummaryTableMarkdownComment = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, @@ -268,17 +284,19 @@ export const getSummaryTableMarkdownComment = ({ formatNumber: (value: number | undefined) => string; ilmPhase: IlmPhase | undefined; indexName: string; + isILMAvailable: boolean; partitionedFieldMetadata: PartitionedFieldMetadata; patternDocsCount: number; sizeInBytes: number | undefined; }): string => - `${getSummaryTableMarkdownHeader()} + `${getSummaryTableMarkdownHeader(isILMAvailable)} ${getSummaryTableMarkdownRow({ docsCount, formatBytes, formatNumber, ilmPhase, indexName, + isILMAvailable, incompatible: partitionedFieldMetadata.incompatible.length, patternDocsCount, sizeInBytes, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/helpers.test.ts index c40f6a73ffa03..e01a63d59c36f 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/helpers.test.ts @@ -30,6 +30,7 @@ import { auditbeatWithAllResults } from '../../mock/pattern_rollup/mock_auditbea import { mockStats } from '../../mock/stats/mock_stats'; import { IndexSummaryTableItem } from '../summary_table/helpers'; import { DataQualityCheckResult } from '../../types'; +import { getIndexNames, getTotalDocsCount } from '../../helpers'; const hot: IlmExplainLifecycleLifecycleExplainManaged = { index: '.ds-packetbeat-8.6.1-2023.02.04-000001', @@ -169,25 +170,26 @@ describe('helpers', () => { }); describe('getIlmPhase', () => { + const isILMAvailable = true; test('it returns undefined when the `ilmExplainRecord` is undefined', () => { - expect(getIlmPhase(undefined)).toBeUndefined(); + expect(getIlmPhase(undefined, isILMAvailable)).toBeUndefined(); }); describe('when the `ilmExplainRecord` is a `IlmExplainLifecycleLifecycleExplainManaged` record', () => { Object.keys(managed).forEach((phase) => test(`it returns the expected phase when 'phase' is '${phase}'`, () => { - expect(getIlmPhase(managed[phase])).toEqual(phase); + expect(getIlmPhase(managed[phase], isILMAvailable)).toEqual(phase); }) ); test(`it returns undefined when the 'phase' is unknown`, () => { - expect(getIlmPhase(other)).toBeUndefined(); + expect(getIlmPhase(other, isILMAvailable)).toBeUndefined(); }); }); describe('when the `ilmExplainRecord` is a `IlmExplainLifecycleLifecycleExplainUnmanaged` record', () => { test('it returns `unmanaged`', () => { - expect(getIlmPhase(unmanaged)).toEqual('unmanaged'); + expect(getIlmPhase(unmanaged, isILMAvailable)).toEqual('unmanaged'); }); }); }); @@ -273,12 +275,14 @@ describe('helpers', () => { pattern: 'auditbeat-*', }, }; + const isILMAvailable = true; test('it returns the expected summary table items', () => { expect( getSummaryTableItems({ ilmExplain: mockIlmExplain, indexNames, + isILMAvailable, pattern, patternDocsCount, results, @@ -317,11 +321,56 @@ describe('helpers', () => { ]); }); + test('it returns the expected summary table items when isILMAvailable is false', () => { + expect( + getSummaryTableItems({ + ilmExplain: mockIlmExplain, + indexNames, + isILMAvailable: false, + pattern, + patternDocsCount, + results, + sortByColumn: defaultSort.sort.field, + sortByDirection: defaultSort.sort.direction, + stats: mockStats, + }) + ).toEqual([ + { + docsCount: 1630289, + ilmPhase: undefined, + incompatible: undefined, + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 733175040, + }, + { + docsCount: 1628343, + ilmPhase: undefined, + incompatible: undefined, + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 731583142, + }, + { + docsCount: 4, + ilmPhase: undefined, + incompatible: 3, + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 28413, + }, + ]); + }); + test('it returns the expected summary table items when `sortByDirection` is ascending', () => { expect( getSummaryTableItems({ ilmExplain: mockIlmExplain, indexNames, + isILMAvailable, pattern, patternDocsCount, results, @@ -365,6 +414,7 @@ describe('helpers', () => { getSummaryTableItems({ ilmExplain: null, // <-- no data indexNames, + isILMAvailable, pattern, patternDocsCount, results: undefined, // <-- no data @@ -410,12 +460,27 @@ describe('helpers', () => { '.ds-packetbeat-8.5.3-2023.02.04-000001', 'auditbeat-custom-index-1', ]; + const isILMAvailable = true; test('returns true when `indexNames` does NOT exist, and the required `stats` and `ilmExplain` are available', () => { expect( shouldCreateIndexNames({ ilmExplain: mockIlmExplain, indexNames: undefined, + isILMAvailable, + newIndexNames: [], + stats: mockStats, + }) + ).toBe(true); + }); + + test('returns true when `isILMAvailable` is false, and the required `stats` is available, and `ilmExplain` is not available', () => { + expect( + shouldCreateIndexNames({ + ilmExplain: null, + indexNames: undefined, + isILMAvailable: false, + newIndexNames: [], stats: mockStats, }) ).toBe(true); @@ -426,6 +491,8 @@ describe('helpers', () => { shouldCreateIndexNames({ ilmExplain: mockIlmExplain, indexNames, + isILMAvailable, + newIndexNames: indexNames, stats: mockStats, }) ).toBe(false); @@ -436,6 +503,8 @@ describe('helpers', () => { shouldCreateIndexNames({ ilmExplain: mockIlmExplain, indexNames: undefined, + isILMAvailable, + newIndexNames: [], stats: null, }) ).toBe(false); @@ -446,6 +515,8 @@ describe('helpers', () => { shouldCreateIndexNames({ ilmExplain: null, indexNames: undefined, + isILMAvailable, + newIndexNames: [], stats: mockStats, }) ).toBe(false); @@ -456,6 +527,8 @@ describe('helpers', () => { shouldCreateIndexNames({ ilmExplain: null, indexNames: undefined, + isILMAvailable, + newIndexNames: [], stats: null, }) ).toBe(false); @@ -466,6 +539,8 @@ describe('helpers', () => { shouldCreateIndexNames({ ilmExplain: null, indexNames, + isILMAvailable, + newIndexNames: [], stats: null, }) ).toBe(false); @@ -473,22 +548,47 @@ describe('helpers', () => { }); describe('shouldCreatePatternRollup', () => { - test('it returns false when the `patternRollup` already exists', () => { + const isILMAvailable = true; + const newIndexNames = getIndexNames({ + stats: mockStats, + ilmExplain: mockIlmExplain, + ilmPhases: ['hot', 'unmanaged'], + isILMAvailable, + }); + const newDocsCount = getTotalDocsCount({ indexNames: newIndexNames, stats: mockStats }); + test('it returns false when the `patternRollup.docsCount` equals newDocsCount', () => { expect( shouldCreatePatternRollup({ error: null, ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount: auditbeatWithAllResults.docsCount as number, patternRollup: auditbeatWithAllResults, stats: mockStats, }) ).toBe(false); }); - test('it returns true when all data was loaded', () => { + test('it returns true when all data and ILMExplain were loaded', () => { expect( shouldCreatePatternRollup({ error: null, ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount, + patternRollup: undefined, + stats: mockStats, + }) + ).toBe(true); + }); + + test('it returns true when all data was loaded and ILM is not available', () => { + expect( + shouldCreatePatternRollup({ + error: null, + ilmExplain: null, + isILMAvailable: false, + newDocsCount, patternRollup: undefined, stats: mockStats, }) @@ -500,6 +600,8 @@ describe('helpers', () => { shouldCreatePatternRollup({ error: null, ilmExplain: null, + isILMAvailable, + newDocsCount, patternRollup: undefined, stats: mockStats, }) @@ -511,6 +613,8 @@ describe('helpers', () => { shouldCreatePatternRollup({ error: null, ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount, patternRollup: undefined, stats: null, }) @@ -522,6 +626,8 @@ describe('helpers', () => { shouldCreatePatternRollup({ error: 'whoops', ilmExplain: null, + isILMAvailable, + newDocsCount, patternRollup: undefined, stats: null, }) @@ -533,6 +639,8 @@ describe('helpers', () => { shouldCreatePatternRollup({ error: 'something went', ilmExplain: null, + isILMAvailable, + newDocsCount, patternRollup: undefined, stats: mockStats, }) @@ -544,6 +652,8 @@ describe('helpers', () => { shouldCreatePatternRollup({ error: 'horribly wrong', ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount, patternRollup: undefined, stats: null, }) @@ -555,6 +665,8 @@ describe('helpers', () => { shouldCreatePatternRollup({ error: 'over here', ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount, patternRollup: undefined, stats: mockStats, }) diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/helpers.ts index 40d0bbfb26293..82fd312a947e5 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/helpers.ts @@ -9,7 +9,7 @@ import type { IlmExplainLifecycleLifecycleExplain, IndicesStatsIndicesStats, } from '@elastic/elasticsearch/lib/api/types'; -import { orderBy } from 'lodash/fp'; +import { isEqual, orderBy } from 'lodash/fp'; import type { IndexSummaryTableItem } from '../summary_table/helpers'; import type { @@ -46,9 +46,10 @@ export const getPhaseCount = ({ }; export const getIlmPhase = ( - ilmExplainRecord: IlmExplainLifecycleLifecycleExplain | undefined + ilmExplainRecord: IlmExplainLifecycleLifecycleExplain | undefined, + isILMAvailable: boolean ): IlmPhase | undefined => { - if (ilmExplainRecord == null) { + if (ilmExplainRecord == null || !isILMAvailable) { return undefined; } @@ -142,6 +143,7 @@ export const getIndexIncompatible = ({ export const getSummaryTableItems = ({ ilmExplain, indexNames, + isILMAvailable, pattern, patternDocsCount, results, @@ -151,6 +153,7 @@ export const getSummaryTableItems = ({ }: { ilmExplain: Record | null; indexNames: string[]; + isILMAvailable: boolean; pattern: string; patternDocsCount: number; results: Record | undefined; @@ -162,7 +165,10 @@ export const getSummaryTableItems = ({ docsCount: getDocsCount({ stats, indexName }), incompatible: getIndexIncompatible({ indexName, results }), indexName, - ilmPhase: ilmExplain != null ? getIlmPhase(ilmExplain[indexName]) : undefined, + ilmPhase: + isILMAvailable && ilmExplain != null + ? getIlmPhase(ilmExplain[indexName], isILMAvailable) + : undefined, pattern, patternDocsCount, sizeInBytes: getSizeInBytes({ stats, indexName }), @@ -174,29 +180,44 @@ export const getSummaryTableItems = ({ export const shouldCreateIndexNames = ({ ilmExplain, indexNames, + isILMAvailable, + newIndexNames, stats, }: { ilmExplain: Record | null; indexNames: string[] | undefined; + isILMAvailable: boolean; + newIndexNames: string[]; stats: Record | null; -}): boolean => indexNames == null && stats != null && ilmExplain != null; +}): boolean => { + return ( + !isEqual(newIndexNames, indexNames) && + stats != null && + ((isILMAvailable && ilmExplain != null) || !isILMAvailable) + ); +}; export const shouldCreatePatternRollup = ({ error, ilmExplain, + isILMAvailable, + newDocsCount, patternRollup, stats, }: { error: string | null; ilmExplain: Record | null; + isILMAvailable: boolean; + newDocsCount: number; patternRollup: PatternRollup | undefined; stats: Record | null; }): boolean => { - if (patternRollup != null) { - return false; // the rollup already exists + if (patternRollup?.docsCount === newDocsCount) { + return false; } - const allDataLoaded: boolean = stats != null && ilmExplain != null; + const allDataLoaded: boolean = + stats != null && ((isILMAvailable && ilmExplain != null) || !isILMAvailable); const errorOccurred: boolean = error != null; return allDataLoaded || errorOccurred; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/index.tsx index b37cea23010fd..93e481fe309ef 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/index.tsx @@ -50,6 +50,7 @@ import * as i18n from './translations'; import type { PatternRollup, SelectedIndex, SortConfig } from '../../types'; import { useIlmExplain } from '../../use_ilm_explain'; import { useStats } from '../../use_stats'; +import { useDataQualityContext } from '../data_quality_context'; const IndexPropertiesContainer = styled.div` margin-bottom: ${euiThemeVars.euiSizeS}; @@ -60,7 +61,9 @@ const EMPTY_INDEX_NAMES: string[] = []; interface Props { addSuccessToast: (toast: { title: string }) => void; + baseTheme: Theme; canUserCreateAndReadCases: () => boolean; + endDate?: string | null; formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; getGroupByFieldsOnClick: ( @@ -90,8 +93,8 @@ interface Props { patternRollup: PatternRollup | undefined; selectedIndex: SelectedIndex | null; setSelectedIndex: (selectedIndex: SelectedIndex | null) => void; + startDate?: string | null; theme?: PartialTheme; - baseTheme: Theme; updatePatternIndexNames: ({ indexNames, pattern, @@ -105,6 +108,7 @@ interface Props { const PatternComponent: React.FC = ({ addSuccessToast, canUserCreateAndReadCases, + endDate, formatBytes, formatNumber, getGroupByFieldsOnClick, @@ -116,17 +120,23 @@ const PatternComponent: React.FC = ({ patternRollup, selectedIndex, setSelectedIndex, + startDate, theme, baseTheme, updatePatternIndexNames, updatePatternRollup, }) => { const containerRef = useRef(null); + const { isILMAvailable } = useDataQualityContext(); const [sorting, setSorting] = useState(defaultSort); const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(MIN_PAGE_SIZE); - const { error: statsError, loading: loadingStats, stats } = useStats(pattern); + const { + error: statsError, + loading: loadingStats, + stats, + } = useStats({ pattern, startDate, endDate }); const { error: ilmExplainError, loading: loadingIlmExplain, ilmExplain } = useIlmExplain(pattern); const loading = useMemo( @@ -154,7 +164,11 @@ const PatternComponent: React.FC = ({ formatNumber={formatNumber} docsCount={getDocsCount({ stats, indexName })} getGroupByFieldsOnClick={getGroupByFieldsOnClick} - ilmPhase={ilmExplain != null ? getIlmPhase(ilmExplain[indexName]) : undefined} + ilmPhase={ + isILMAvailable && ilmExplain != null + ? getIlmPhase(ilmExplain?.[indexName], isILMAvailable) + : undefined + } indexId={getIndexId({ stats, indexName })} indexName={indexName} isAssistantEnabled={isAssistantEnabled} @@ -179,6 +193,7 @@ const PatternComponent: React.FC = ({ stats, getGroupByFieldsOnClick, ilmExplain, + isILMAvailable, isAssistantEnabled, openCreateCaseFlyout, pattern, @@ -189,13 +204,17 @@ const PatternComponent: React.FC = ({ ] ); - const ilmExplainPhaseCounts = useMemo(() => getIlmExplainPhaseCounts(ilmExplain), [ilmExplain]); + const ilmExplainPhaseCounts = useMemo( + () => (isILMAvailable ? getIlmExplainPhaseCounts(ilmExplain) : undefined), + [ilmExplain, isILMAvailable] + ); const items = useMemo( () => getSummaryTableItems({ ilmExplain, indexNames: indexNames ?? EMPTY_INDEX_NAMES, + isILMAvailable, pattern, patternDocsCount: patternRollup?.docsCount ?? 0, results: patternRollup?.results, @@ -206,6 +225,7 @@ const PatternComponent: React.FC = ({ [ ilmExplain, indexNames, + isILMAvailable, pattern, patternRollup?.docsCount, patternRollup?.results, @@ -216,27 +236,44 @@ const PatternComponent: React.FC = ({ ); useEffect(() => { - if (shouldCreateIndexNames({ indexNames, stats, ilmExplain })) { + const newIndexNames = getIndexNames({ stats, ilmExplain, ilmPhases, isILMAvailable }); + const newDocsCount = getTotalDocsCount({ indexNames: newIndexNames, stats }); + + if ( + shouldCreateIndexNames({ + indexNames, + ilmExplain, + isILMAvailable, + newIndexNames, + stats, + }) + ) { updatePatternIndexNames({ - indexNames: getIndexNames({ stats, ilmExplain, ilmPhases }), + indexNames: newIndexNames, pattern, }); } - if (shouldCreatePatternRollup({ error, patternRollup, stats, ilmExplain })) { + if ( + shouldCreatePatternRollup({ + error, + ilmExplain, + isILMAvailable, + newDocsCount, + patternRollup, + stats, + }) + ) { updatePatternRollup({ - docsCount: getTotalDocsCount({ - indexNames: getIndexNames({ stats, ilmExplain, ilmPhases }), - stats, - }), + docsCount: newDocsCount, error, ilmExplain, ilmExplainPhaseCounts, - indices: getIndexNames({ stats, ilmExplain, ilmPhases }).length, + indices: getIndexNames({ stats, ilmExplain, ilmPhases, isILMAvailable }).length, pattern, results: undefined, sizeInBytes: getTotalSizeInBytes({ - indexNames: getIndexNames({ stats, ilmExplain, ilmPhases }), + indexNames: getIndexNames({ stats, ilmExplain, ilmPhases, isILMAvailable }), stats, }), stats, @@ -248,6 +285,7 @@ const PatternComponent: React.FC = ({ ilmExplainPhaseCounts, ilmPhases, indexNames, + isILMAvailable, pattern, patternRollup, stats, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/pattern_summary/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/pattern_summary/index.tsx index 233de9fc93a1f..1ef9443d7c9c5 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/pattern_summary/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/pattern_summary/index.tsx @@ -15,7 +15,7 @@ import { StatsRollup } from './stats_rollup'; interface Props { formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; - ilmExplainPhaseCounts: IlmExplainPhaseCounts; + ilmExplainPhaseCounts: IlmExplainPhaseCounts | undefined; incompatible: number | undefined; indices: number | undefined; indicesChecked: number | undefined; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/pattern_summary/pattern_label/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/pattern_summary/pattern_label/index.tsx index f421da8d2bf35..34d6f56a8594a 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/pattern_summary/pattern_label/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/pattern/pattern_summary/pattern_label/index.tsx @@ -23,7 +23,7 @@ interface Props { incompatible: number | undefined; indices: number | undefined; indicesChecked: number | undefined; - ilmExplainPhaseCounts: IlmExplainPhaseCounts; + ilmExplainPhaseCounts: IlmExplainPhaseCounts | undefined; pattern: string; } @@ -63,7 +63,9 @@ const PatternLabelComponent: React.FC = ({
    - + {ilmExplainPhaseCounts && ( + + )} ); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/storage_treemap/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/storage_treemap/index.test.tsx index 6485f3c1e4717..f1ae399c4da23 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/storage_treemap/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/storage_treemap/index.test.tsx @@ -42,6 +42,7 @@ const patternRollups: Record = { const flattenedBuckets = getFlattenedBuckets({ ilmPhases, + isILMAvailable: true, patternRollups, }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/helpers.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/helpers.test.tsx index e913d38dbb07c..6ab874eeac5b6 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/helpers.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/helpers.test.tsx @@ -21,6 +21,7 @@ import { getResultToolTip, getShowPagination, getSummaryTableColumns, + getSummaryTableILMPhaseColumn, getToggleButtonId, IndexSummaryTableItem, } from './helpers'; @@ -132,6 +133,7 @@ describe('helpers', () => { describe('getSummaryTableColumns', () => { const indexName = '.ds-auditbeat-8.6.1-2023.02.07-000001'; + const isILMAvailable = true; const indexSummaryTableItem: IndexSummaryTableItem = { indexName, @@ -153,6 +155,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }).map((x) => omit('render', x)); @@ -194,6 +197,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -219,6 +223,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -242,6 +247,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded, }); @@ -273,6 +279,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -295,6 +302,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -321,6 +329,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -344,6 +353,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -367,6 +377,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -401,6 +412,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -422,6 +434,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -440,12 +453,26 @@ describe('helpers', () => { }); }); + describe('getSummaryTableILMPhaseColumn', () => { + test('it returns the expected column configuration when `isILMAvailable` is true', () => { + const column = getSummaryTableILMPhaseColumn(isILMAvailable); + expect(column.length).toEqual(1); + expect(column[0].name).toEqual('ILM Phase'); + }); + + test('it returns an emptry array when `isILMAvailable` is false', () => { + const column = getSummaryTableILMPhaseColumn(false); + expect(column.length).toEqual(0); + }); + }); + describe('ilmPhase column render()', () => { test('it renders the expected ilmPhase badge content', () => { const columns = getSummaryTableColumns({ formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -471,6 +498,32 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, + pattern: 'auditbeat-*', + toggleExpanded: jest.fn(), + }); + const ilmPhaseRender = (columns[5] as EuiTableFieldDataColumnType) + .render; + + render( + + {ilmPhaseRender != null && ilmPhaseRender(ilmPhaseIsUndefined, ilmPhaseIsUndefined)} + + ); + + expect(screen.queryByTestId('ilmPhase')).not.toBeInTheDocument(); + }); + + test('it does NOT render the ilmPhase badge when `isILMAvailable` is false', () => { + const ilmPhaseIsUndefined: IndexSummaryTableItem = { + ...indexSummaryTableItem, + }; + + const columns = getSummaryTableColumns({ + formatBytes, + formatNumber, + itemIdToExpandedRowMap: {}, + isILMAvailable: false, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); @@ -493,6 +546,7 @@ describe('helpers', () => { formatBytes, formatNumber, itemIdToExpandedRowMap: {}, + isILMAvailable, pattern: 'auditbeat-*', toggleExpanded: jest.fn(), }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/helpers.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/helpers.tsx index 89e0d78fddb6b..f80678fff8cb2 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/helpers.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/helpers.tsx @@ -95,16 +95,40 @@ export const getToggleButtonId = ({ pattern: string; }): string => (isExpanded ? `collapse${indexName}${pattern}` : `expand${indexName}${pattern}`); +export const getSummaryTableILMPhaseColumn = ( + isILMAvailable: boolean +): Array> => + isILMAvailable + ? [ + { + field: 'ilmPhase', + name: i18n.ILM_PHASE, + render: (_, { ilmPhase }) => + ilmPhase != null ? ( + + + {ilmPhase} + + + ) : null, + sortable: true, + truncateText: false, + }, + ] + : []; + export const getSummaryTableColumns = ({ formatBytes, formatNumber, itemIdToExpandedRowMap, + isILMAvailable, pattern, toggleExpanded, }: { formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; itemIdToExpandedRowMap: Record; + isILMAvailable: boolean; pattern: string; toggleExpanded: (indexName: string) => void; }): Array> => [ @@ -201,20 +225,7 @@ export const getSummaryTableColumns = ({ sortable: true, truncateText: false, }, - { - field: 'ilmPhase', - name: i18n.ILM_PHASE, - render: (_, { ilmPhase }) => - ilmPhase != null ? ( - - - {ilmPhase} - - - ) : null, - sortable: true, - truncateText: false, - }, + ...getSummaryTableILMPhaseColumn(isILMAvailable), { field: 'sizeInBytes', name: i18n.SIZE, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/index.test.tsx index 235ec61a204af..720943b0d2bb8 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/index.test.tsx @@ -48,6 +48,7 @@ const pattern = 'auditbeat-*'; const items = getSummaryTableItems({ ilmExplain: mockIlmExplain, indexNames: indexNames ?? [], + isILMAvailable: true, pattern, patternDocsCount: auditbeatWithAllResults?.docsCount ?? 0, results: auditbeatWithAllResults?.results, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/index.tsx index 2dd2c4e214dc0..a230510029222 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/summary_table/index.tsx @@ -13,6 +13,7 @@ import type { IndexSummaryTableItem } from './helpers'; import { getShowPagination } from './helpers'; import { defaultSort, MIN_PAGE_SIZE } from '../pattern/helpers'; import { SortConfig } from '../../types'; +import { useDataQualityContext } from '../data_quality_context'; export interface Props { formatBytes: (value: number | undefined) => string; @@ -21,12 +22,14 @@ export interface Props { formatBytes, formatNumber, itemIdToExpandedRowMap, + isILMAvailable, pattern, toggleExpanded, }: { formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; itemIdToExpandedRowMap: Record; + isILMAvailable: boolean; pattern: string; toggleExpanded: (indexName: string) => void; }) => Array>; @@ -57,16 +60,26 @@ const SummaryTableComponent: React.FC = ({ sorting, toggleExpanded, }) => { + const { isILMAvailable } = useDataQualityContext(); const columns = useMemo( () => getTableColumns({ formatBytes, formatNumber, itemIdToExpandedRowMap, + isILMAvailable, pattern, toggleExpanded, }), - [formatBytes, formatNumber, getTableColumns, itemIdToExpandedRowMap, pattern, toggleExpanded] + [ + formatBytes, + formatNumber, + getTableColumns, + isILMAvailable, + itemIdToExpandedRowMap, + pattern, + toggleExpanded, + ] ); const getItemId = useCallback((item: IndexSummaryTableItem) => item.indexName, []); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/helpers.test.ts index ab23e2265399b..ffa3e0bde633d 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/helpers.test.ts @@ -79,6 +79,7 @@ ${ECS_IS_A_PERMISSIVE_SCHEMA} formatNumber, ilmPhase: 'unmanaged', indexName: 'auditbeat-custom-index-1', + isILMAvailable: true, partitionedFieldMetadata: mockPartitionedFieldMetadata, patternDocsCount: 57410, sizeInBytes: 28413, @@ -91,5 +92,27 @@ ${ECS_IS_A_PERMISSIVE_SCHEMA} '#### Custom fields - auditbeat-custom-index-1\n\n\n| Field | Index mapping type | \n|-------|--------------------|\n| host.name.keyword | `keyword` | `--` |\n| some.field | `text` | `--` |\n| some.field.keyword | `keyword` | `--` |\n| source.ip.keyword | `keyword` | `--` |\n', ]); }); + + test('it returns the expected comment without ILM Phase when isILMAvailable is false', () => { + expect( + getAllCustomMarkdownComments({ + docsCount: 4, + formatBytes, + formatNumber, + ilmPhase: 'unmanaged', + indexName: 'auditbeat-custom-index-1', + isILMAvailable: false, + partitionedFieldMetadata: mockPartitionedFieldMetadata, + patternDocsCount: 57410, + sizeInBytes: 28413, + }) + ).toEqual([ + '### auditbeat-custom-index-1\n', + '| Result | Index | Docs | Incompatible fields | Size |\n|--------|-------|------|---------------------|------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 | 27.7KB |\n\n', + '### **Incompatible fields** `3` **Custom fields** `4` **ECS compliant fields** `2` **All fields** `9`\n', + `#### 4 Custom field mappings\n\nThese fields are not defined by the Elastic Common Schema (ECS), version ${EcsVersion}.\n\nECS is a permissive schema. If your events have additional data that cannot be mapped to ECS, you can simply add them to your events, using custom field names.\n`, + '#### Custom fields - auditbeat-custom-index-1\n\n\n| Field | Index mapping type | \n|-------|--------------------|\n| host.name.keyword | `keyword` | `--` |\n| some.field | `text` | `--` |\n| some.field.keyword | `keyword` | `--` |\n| source.ip.keyword | `keyword` | `--` |\n', + ]); + }); }); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/helpers.ts index 7701db46d6c98..9d1f6362aa91d 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/helpers.ts @@ -51,6 +51,7 @@ export const getAllCustomMarkdownComments = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, @@ -59,6 +60,7 @@ export const getAllCustomMarkdownComments = ({ formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; ilmPhase: IlmPhase | undefined; + isILMAvailable: boolean; indexName: string; partitionedFieldMetadata: PartitionedFieldMetadata; patternDocsCount: number; @@ -71,6 +73,7 @@ export const getAllCustomMarkdownComments = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/index.tsx index 09f7136d7108a..019e65e891474 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/custom_tab/index.tsx @@ -24,6 +24,7 @@ import { getAllCustomMarkdownComments, showCustomCallout } from './helpers'; import * as i18n from '../../index_properties/translations'; import { COPIED_RESULTS_TOAST_TITLE } from '../../../translations'; import type { IlmPhase, PartitionedFieldMetadata } from '../../../types'; +import { useDataQualityContext } from '../../data_quality_context'; interface Props { addSuccessToast: (toast: { title: string }) => void; @@ -48,6 +49,7 @@ const CustomTabComponent: React.FC = ({ patternDocsCount, sizeInBytes, }) => { + const { isILMAvailable } = useDataQualityContext(); const markdownComments: string[] = useMemo( () => getAllCustomMarkdownComments({ @@ -56,6 +58,7 @@ const CustomTabComponent: React.FC = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, @@ -66,6 +69,7 @@ const CustomTabComponent: React.FC = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/helpers.test.ts index 7c690ef143f6b..a33c65c9fd315 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/helpers.test.ts @@ -349,6 +349,7 @@ ${MAPPINGS_THAT_CONFLICT_WITH_ECS} formatBytes, formatNumber, ilmPhase: 'unmanaged', + isILMAvailable: true, indexName: 'auditbeat-custom-index-1', partitionedFieldMetadata: mockPartitionedFieldMetadata, patternDocsCount: 57410, @@ -376,6 +377,7 @@ ${MAPPINGS_THAT_CONFLICT_WITH_ECS} formatNumber, ilmPhase: 'unmanaged', indexName: 'auditbeat-custom-index-1', + isILMAvailable: true, partitionedFieldMetadata: emptyIncompatible, patternDocsCount: 57410, sizeInBytes: 28413, @@ -387,5 +389,31 @@ ${MAPPINGS_THAT_CONFLICT_WITH_ECS} '\n\n\n', ]); }); + + test('it returns the expected comment when `isILMAvailable` is false', () => { + const emptyIncompatible: PartitionedFieldMetadata = { + ...mockPartitionedFieldMetadata, + incompatible: [], // <-- empty + }; + + expect( + getAllIncompatibleMarkdownComments({ + docsCount: 4, + formatBytes, + formatNumber, + ilmPhase: 'unmanaged', + indexName: 'auditbeat-custom-index-1', + isILMAvailable: false, + partitionedFieldMetadata: emptyIncompatible, + patternDocsCount: 57410, + sizeInBytes: 28413, + }) + ).toEqual([ + '### auditbeat-custom-index-1\n', + '| Result | Index | Docs | Incompatible fields | Size |\n|--------|-------|------|---------------------|------|\n| ✅ | auditbeat-custom-index-1 | 4 (0.0%) | 0 | 27.7KB |\n\n', + '### **Incompatible fields** `0` **Custom fields** `4` **ECS compliant fields** `2` **All fields** `9`\n', + '\n\n\n', + ]); + }); }); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/helpers.ts index c354b4ef1e8db..bbda7ca0026ad 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/helpers.ts @@ -134,6 +134,7 @@ export const getAllIncompatibleMarkdownComments = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, @@ -143,6 +144,7 @@ export const getAllIncompatibleMarkdownComments = ({ formatNumber: (value: number | undefined) => string; ilmPhase: IlmPhase | undefined; indexName: string; + isILMAvailable: boolean; partitionedFieldMetadata: PartitionedFieldMetadata; patternDocsCount: number; sizeInBytes: number | undefined; @@ -169,6 +171,7 @@ export const getAllIncompatibleMarkdownComments = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/index.tsx index e0e26f3928bde..e1b1bdfc9a403 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/index.tsx @@ -42,6 +42,7 @@ import { } from '../../../translations'; import type { IlmPhase, PartitionedFieldMetadata } from '../../../types'; import { DATA_QUALITY_DASHBOARD_CONVERSATION_ID } from '../summary_tab/callout_summary/translations'; +import { useDataQualityContext } from '../../data_quality_context'; interface Props { addSuccessToast: (toast: { title: string }) => void; @@ -72,6 +73,7 @@ const IncompatibleTabComponent: React.FC = ({ patternDocsCount, sizeInBytes, }) => { + const { isILMAvailable } = useDataQualityContext(); const body = useMemo(() => , []); const title = useMemo(() => , []); const incompatibleMappings = useMemo( @@ -90,6 +92,7 @@ const IncompatibleTabComponent: React.FC = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, @@ -100,6 +103,7 @@ const IncompatibleTabComponent: React.FC = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/callout_summary/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/callout_summary/index.tsx index ba3aebc501010..d9403b7159e9f 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/callout_summary/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/callout_summary/index.tsx @@ -24,6 +24,7 @@ import { } from '../../../../translations'; import type { IlmPhase, PartitionedFieldMetadata } from '../../../../types'; import { DATA_QUALITY_DASHBOARD_CONVERSATION_ID } from './translations'; +import { useDataQualityContext } from '../../../data_quality_context'; interface Props { addSuccessToast: (toast: { title: string }) => void; @@ -56,6 +57,7 @@ const CalloutSummaryComponent: React.FC = ({ patternDocsCount, sizeInBytes, }) => { + const { isILMAvailable } = useDataQualityContext(); const markdownComments: string[] = useMemo( () => getMarkdownComments({ @@ -64,6 +66,7 @@ const CalloutSummaryComponent: React.FC = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, pattern, patternDocsCount, @@ -75,6 +78,7 @@ const CalloutSummaryComponent: React.FC = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, pattern, patternDocsCount, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/helpers.test.ts index 64e78a4a88cfb..40934fcd9a1bb 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/helpers.test.ts @@ -146,6 +146,7 @@ describe('helpers', () => { const defaultNumberFormat = '0,0.[000]'; const formatNumber = (value: number | undefined) => value != null ? numeral(value).format(defaultNumberFormat) : EMPTY_STAT; + const isILMAvailable = true; test('it returns the expected comment when the index has incompatible fields ', () => { expect( @@ -155,6 +156,7 @@ describe('helpers', () => { formatNumber, ilmPhase: 'unmanaged', indexName: 'auditbeat-custom-index-1', + isILMAvailable, partitionedFieldMetadata: mockPartitionedFieldMetadata, pattern: 'auditbeat-*', patternDocsCount: 57410, @@ -182,6 +184,7 @@ describe('helpers', () => { formatNumber, ilmPhase: 'unmanaged', indexName: 'auditbeat-custom-index-1', + isILMAvailable, partitionedFieldMetadata: noIncompatible, pattern: 'auditbeat-*', patternDocsCount: 57410, @@ -217,6 +220,7 @@ describe('helpers', () => { formatNumber, ilmPhase: 'unmanaged', indexName: 'auditbeat-custom-empty-index-1', + isILMAvailable, partitionedFieldMetadata: emptyIndex, pattern: 'auditbeat-*', patternDocsCount: 57410, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/helpers.ts index 1f728e3b60c86..c720eba85f4ca 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/helpers.ts @@ -83,6 +83,7 @@ export const getMarkdownComments = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, @@ -92,6 +93,7 @@ export const getMarkdownComments = ({ formatNumber: (value: number | undefined) => string; ilmPhase: IlmPhase | undefined; indexName: string; + isILMAvailable: boolean; partitionedFieldMetadata: PartitionedFieldMetadata; pattern: string; patternDocsCount: number; @@ -104,6 +106,7 @@ export const getMarkdownComments = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.test.ts index 81e968bfe73a4..12d3d26f64ae3 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.test.ts @@ -79,6 +79,7 @@ const ecsMetadata: Record = EcsFlat as unknown as Record { describe('getIndexNames', () => { + const isILMAvailable = true; const ilmPhases = ['hot', 'warm', 'unmanaged']; test('returns the expected index names when they have an ILM phase included in the ilmPhases list', () => { @@ -86,6 +87,7 @@ describe('helpers', () => { getIndexNames({ ilmExplain: mockIlmExplain, // <-- the mock indexes have 'hot' ILM phases ilmPhases, + isILMAvailable, stats: mockStats, }) ).toEqual([ @@ -100,6 +102,7 @@ describe('helpers', () => { getIndexNames({ ilmExplain: mockIlmExplain, // <-- the mock indexes have 'hot' and 'unmanaged' ILM phases... ilmPhases: ['warm', 'unmanaged'], // <-- ...but we don't ask for 'hot' + isILMAvailable, stats: mockStats, }) ).toEqual(['auditbeat-custom-index-1']); // <-- the 'unmanaged' index @@ -116,6 +119,7 @@ describe('helpers', () => { getIndexNames({ ilmExplain: ilmExplainWithMissingIndex, // <-- the mock indexes have 'hot' ILM phases... ilmPhases: ['hot', 'warm', 'unmanaged'], + isILMAvailable, stats: mockStats, }) ).toEqual(['.ds-packetbeat-8.5.3-2023.02.04-000001', 'auditbeat-custom-index-1']); // <-- only includes two of the three indices, because the other one is missing an ILM explain record @@ -126,6 +130,7 @@ describe('helpers', () => { getIndexNames({ ilmExplain: mockIlmExplain, ilmPhases: [], + isILMAvailable, stats: mockStats, }) ).toEqual([]); @@ -136,6 +141,7 @@ describe('helpers', () => { getIndexNames({ ilmExplain: null, ilmPhases, + isILMAvailable, stats: mockStats, }) ).toEqual([]); @@ -146,6 +152,7 @@ describe('helpers', () => { getIndexNames({ ilmExplain: mockIlmExplain, ilmPhases, + isILMAvailable, stats: null, }) ).toEqual([]); @@ -156,6 +163,7 @@ describe('helpers', () => { getIndexNames({ ilmExplain: null, ilmPhases, + isILMAvailable, stats: null, }) ).toEqual([]); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts index 6b0d75e1308c9..87ac9df08ad6c 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts @@ -31,17 +31,21 @@ const EMPTY_INDEX_NAMES: string[] = []; export const getIndexNames = ({ ilmExplain, ilmPhases, + isILMAvailable, stats, }: { ilmExplain: Record | null; ilmPhases: string[]; + isILMAvailable: boolean; stats: Record | null; }): string[] => { - if (ilmExplain != null && stats != null) { + if (((isILMAvailable && ilmExplain != null) || !isILMAvailable) && stats != null) { const allIndexNames = Object.keys(stats); - const filteredByIlmPhase = allIndexNames.filter((indexName) => - ilmPhases.includes(getIlmPhase(ilmExplain[indexName]) ?? '') - ); + const filteredByIlmPhase = isILMAvailable + ? allIndexNames.filter((indexName) => + ilmPhases.includes(getIlmPhase(ilmExplain?.[indexName], isILMAvailable) ?? '') + ) + : allIndexNames; return filteredByIlmPhase; } else { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/index.test.tsx index d9cccb4259caf..e7e72221d18f5 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/index.test.tsx @@ -28,6 +28,7 @@ describe('DataQualityPanel', () => { httpFetch={jest.fn()} ilmPhases={ilmPhases} isAssistantEnabled={true} + isILMAvailable={true} lastChecked={''} openCreateCaseFlyout={jest.fn()} patterns={[]} @@ -63,6 +64,7 @@ describe('DataQualityPanel', () => { httpFetch={jest.fn()} ilmPhases={ilmPhases} isAssistantEnabled={true} + isILMAvailable={true} lastChecked={''} openCreateCaseFlyout={jest.fn()} patterns={[]} diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/index.tsx index 0a6e0d6a0ccd1..8d95e71464728 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/index.tsx @@ -26,9 +26,11 @@ import { ReportDataQualityCheckAllCompleted, ReportDataQualityIndexChecked } fro interface Props { addSuccessToast: (toast: { title: string }) => void; + baseTheme: Theme; canUserCreateAndReadCases: () => boolean; defaultNumberFormat: string; defaultBytesFormat: string; + endDate?: string | null; getGroupByFieldsOnClick: ( elements: Array< | FlameElementEvent @@ -45,6 +47,7 @@ interface Props { httpFetch: HttpHandler; ilmPhases: string[]; isAssistantEnabled: boolean; + isILMAvailable: boolean; lastChecked: string; openCreateCaseFlyout: ({ comments, @@ -57,8 +60,8 @@ interface Props { reportDataQualityIndexChecked?: ReportDataQualityIndexChecked; reportDataQualityCheckAllCompleted?: ReportDataQualityCheckAllCompleted; setLastChecked: (lastChecked: string) => void; + startDate?: string | null; theme?: PartialTheme; - baseTheme: Theme; } /** Renders the `Data Quality` dashboard content */ @@ -68,16 +71,19 @@ const DataQualityPanelComponent: React.FC = ({ canUserCreateAndReadCases, defaultBytesFormat, defaultNumberFormat, + endDate, getGroupByFieldsOnClick, httpFetch, ilmPhases, isAssistantEnabled, + isILMAvailable, lastChecked, openCreateCaseFlyout, patterns, reportDataQualityIndexChecked, reportDataQualityCheckAllCompleted, setLastChecked, + startDate, theme, }) => { const formatBytes = useCallback( @@ -98,10 +104,15 @@ const DataQualityPanelComponent: React.FC = ({ ); return ( - + = ({ openCreateCaseFlyout={openCreateCaseFlyout} patterns={patterns} setLastChecked={setLastChecked} + startDate={startDate} theme={theme} baseTheme={baseTheme} /> diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx index 90fdc078534fd..9bbdf52e606bb 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/test_providers/test_providers.tsx @@ -17,12 +17,13 @@ import { DataQualityProvider } from '../../data_quality_panel/data_quality_conte interface Props { children: React.ReactNode; + isILMAvailable?: boolean; } window.scrollTo = jest.fn(); /** A utility for wrapping children in the providers required to run tests */ -export const TestProvidersComponent: React.FC = ({ children }) => { +export const TestProvidersComponent: React.FC = ({ children, isILMAvailable = true }) => { const http = httpServiceMock.createSetupContract({ basePath: '/test' }); const actionTypeRegistry = actionTypeRegistryMock.create(); const mockGetInitialConversations = jest.fn(() => ({})); @@ -45,6 +46,7 @@ export const TestProvidersComponent: React.FC = ({ children }) => { = ({ children }) => { setDefaultAllowReplacement={jest.fn()} http={mockHttp} > - + {children} diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.test.tsx index cff820a4c532c..90cd0906c137a 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.test.tsx @@ -20,8 +20,15 @@ const mockTelemetryEvents = { reportDataQualityIndexChecked: mockReportDataQualityIndexChecked, reportDataQualityCheckAllCompleted: mockReportDataQualityCheckAllClicked, }; -const ContextWrapper: React.FC = ({ children }) => ( - +const ContextWrapper: React.FC<{ children: React.ReactNode; isILMAvailable: boolean }> = ({ + children, + isILMAvailable = true, +}) => ( + {children} ); @@ -59,6 +66,34 @@ describe('useIlmExplain', () => { }); }); + describe('skip ilm api when isILMAvailable is false', () => { + let ilmExplainResult: UseIlmExplain | undefined; + + beforeEach(async () => { + const { result, waitForNextUpdate } = renderHook(() => useIlmExplain(pattern), { + wrapper: ({ children }) => ( + + {children} + + ), + }); + await waitForNextUpdate(); + ilmExplainResult = await result.current; + }); + + test('it returns the expected ilmExplain map', async () => { + expect(ilmExplainResult?.ilmExplain).toEqual(null); + }); + + test('it returns loading: false, because the request is aborted', async () => { + expect(ilmExplainResult?.loading).toBe(false); + }); + }); + describe('fetch rejects with an error', () => { let ilmExplainResult: UseIlmExplain | undefined; const errorMessage = 'simulated error'; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx index 64b2765a39df3..ae643745bd805 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx @@ -20,7 +20,7 @@ export interface UseIlmExplain { } export const useIlmExplain = (pattern: string): UseIlmExplain => { - const { httpFetch } = useDataQualityContext(); + const { httpFetch, isILMAvailable } = useDataQualityContext(); const [ilmExplain, setIlmExplain] = useState { async function fetchData() { try { const encodedIndexName = encodeURIComponent(`${pattern}`); + if (!isILMAvailable) { + abortController.abort(); + } const response = await httpFetch>( `${ILM_EXPLAIN_ENDPOINT}/${encodedIndexName}`, @@ -51,9 +54,7 @@ export const useIlmExplain = (pattern: string): UseIlmExplain => { setError(i18n.ERROR_LOADING_ILM_EXPLAIN(e.message)); } } finally { - if (!abortController.signal.aborted) { - setLoading(false); - } + setLoading(false); } } @@ -62,7 +63,7 @@ export const useIlmExplain = (pattern: string): UseIlmExplain => { return () => { abortController.abort(); }; - }, [httpFetch, pattern, setError]); + }, [httpFetch, isILMAvailable, pattern, setError]); return { ilmExplain, error, loading }; }; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/index.test.tsx index cb0165c68d942..06006d3c5a3cf 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/index.test.tsx @@ -22,7 +22,11 @@ const mockTelemetryEvents = { }; const ContextWrapper: React.FC = ({ children }) => ( - + {children} ); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/helpers.test.ts index f25903adff823..2b53b44a64027 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/helpers.test.ts @@ -158,6 +158,7 @@ describe('helpers', () => { formatBytes, formatNumber, indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + isILMAvailable: true, partitionedFieldMetadata: mockPartitionedFieldMetadata, pattern: 'packetbeat-*', patternRollups: { @@ -257,6 +258,7 @@ describe('helpers', () => { formatBytes, formatNumber, indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + isILMAvailable: true, partitionedFieldMetadata: mockPartitionedFieldMetadata, pattern: 'packetbeat-*', patternRollups: { @@ -351,6 +353,7 @@ describe('helpers', () => { formatBytes, formatNumber, indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + isILMAvailable: true, partitionedFieldMetadata: null, // <-- pattern: 'packetbeat-*', patternRollups: { @@ -444,6 +447,7 @@ describe('helpers', () => { formatBytes, formatNumber, indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + isILMAvailable: true, partitionedFieldMetadata: mockPartitionedFieldMetadata, pattern: 'packetbeat-*', patternRollups: { @@ -501,6 +505,7 @@ describe('helpers', () => { formatBytes, formatNumber, indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + isILMAvailable: true, partitionedFieldMetadata: mockPartitionedFieldMetadata, pattern: 'this-pattern-is-not-in-pattern-rollups', // <-- patternRollups: shouldNotBeModified, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/helpers.ts index dbad0364904f5..ecd00ce71a8f6 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/helpers.ts @@ -90,6 +90,7 @@ export const updateResultOnCheckCompleted = ({ formatBytes, formatNumber, indexName, + isILMAvailable, partitionedFieldMetadata, pattern, patternRollups, @@ -98,6 +99,7 @@ export const updateResultOnCheckCompleted = ({ formatBytes: (value: number | undefined) => string; formatNumber: (value: number | undefined) => string; indexName: string; + isILMAvailable: boolean; partitionedFieldMetadata: PartitionedFieldMetadata | null; pattern: string; patternRollups: Record; @@ -108,7 +110,7 @@ export const updateResultOnCheckCompleted = ({ const ilmExplain = patternRollup.ilmExplain; const ilmPhase: IlmPhase | undefined = - ilmExplain != null ? getIlmPhase(ilmExplain[indexName]) : undefined; + ilmExplain != null ? getIlmPhase(ilmExplain[indexName], isILMAvailable) : undefined; const docsCount = getIndexDocsCountFromRollup({ indexName, @@ -127,6 +129,7 @@ export const updateResultOnCheckCompleted = ({ formatNumber, ilmPhase, indexName, + isILMAvailable, partitionedFieldMetadata, patternDocsCount, sizeInBytes, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/index.tsx index 652c07ce29275..60c2ac8899908 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_results_rollup/index.tsx @@ -53,7 +53,7 @@ interface UseResultsRollup { export const useResultsRollup = ({ ilmPhases, patterns }: Props): UseResultsRollup => { const [patternIndexNames, setPatternIndexNames] = useState>({}); const [patternRollups, setPatternRollups] = useState>({}); - const { telemetryEvents } = useDataQualityContext(); + const { telemetryEvents, isILMAvailable } = useDataQualityContext(); const updatePatternRollup = useCallback((patternRollup: PatternRollup) => { setPatternRollups((current) => onPatternRollupUpdated({ patternRollup, patternRollups: current }) @@ -101,6 +101,7 @@ export const useResultsRollup = ({ ilmPhases, patterns }: Props): UseResultsRoll formatBytes, formatNumber, indexName, + isILMAvailable, partitionedFieldMetadata, pattern, patternRollups: current, @@ -119,7 +120,7 @@ export const useResultsRollup = ({ ilmPhases, patterns }: Props): UseResultsRoll batchId, ecsVersion: EcsVersion, errorCount: error ? 1 : 0, - ilmPhase: getIlmPhase(ilmExplain[indexName]), + ilmPhase: getIlmPhase(ilmExplain[indexName], isILMAvailable), indexId, indexName, isCheckAll: true, @@ -157,7 +158,7 @@ export const useResultsRollup = ({ ilmPhases, patterns }: Props): UseResultsRoll return updated; }); }, - [patternRollups, telemetryEvents] + [isILMAvailable, patternRollups, telemetryEvents] ); useEffect(() => { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.test.tsx index 30960a7daa874..de63f40e361c4 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.test.tsx @@ -22,25 +22,64 @@ const mockTelemetryEvents = { }; const ContextWrapper: React.FC = ({ children }) => ( - + + {children} + +); + +const ContextWrapperILMNotAvailable: React.FC = ({ children }) => ( + {children} ); const pattern = 'auditbeat-*'; +const startDate = `now-7d`; +const endDate = `now`; +const params = { + pattern, +}; describe('useStats', () => { beforeEach(() => { jest.clearAllMocks(); }); + describe('query with date range when ILM is not available', () => { + const queryParams = { + isILMAvailable: false, + startDate, + endDate, + }; + + beforeEach(async () => { + mockHttpFetch.mockResolvedValue(mockStatsGreenIndex); + + const { waitForNextUpdate } = renderHook(() => useStats({ pattern, startDate, endDate }), { + wrapper: ContextWrapperILMNotAvailable, + }); + await waitForNextUpdate(); + }); + test(`it calls the stats api with the expected params`, async () => { + expect(mockHttpFetch.mock.calls[0][1].query).toEqual(queryParams); + }); + }); + describe('successful response from the stats api', () => { let statsResult: UseStats | undefined; beforeEach(async () => { mockHttpFetch.mockResolvedValue(mockStatsGreenIndex); - const { result, waitForNextUpdate } = renderHook(() => useStats(pattern), { + const { result, waitForNextUpdate } = renderHook(() => useStats(params), { wrapper: ContextWrapper, }); await waitForNextUpdate(); @@ -58,6 +97,10 @@ describe('useStats', () => { test('it returns a null error, because no errors occurred', async () => { expect(statsResult?.error).toBeNull(); }); + + test(`it calls the stats api with the expected params`, async () => { + expect(mockHttpFetch.mock.calls[0][1].query).toEqual({ isILMAvailable: true }); + }); }); describe('fetch rejects with an error', () => { @@ -67,7 +110,7 @@ describe('useStats', () => { beforeEach(async () => { mockHttpFetch.mockRejectedValue(new Error(errorMessage)); - const { result, waitForNextUpdate } = renderHook(() => useStats(pattern), { + const { result, waitForNextUpdate } = renderHook(() => useStats(params), { wrapper: ContextWrapper, }); await waitForNextUpdate(); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx index d929bb3368345..6875dad3d4dfc 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx @@ -7,6 +7,7 @@ import type { IndicesStatsIndicesStats } from '@elastic/elasticsearch/lib/api/types'; import { useEffect, useState } from 'react'; +import { HttpFetchQuery } from '@kbn/core/public'; import { useDataQualityContext } from '../data_quality_panel/data_quality_context'; import * as i18n from '../translations'; @@ -19,8 +20,16 @@ export interface UseStats { loading: boolean; } -export const useStats = (pattern: string): UseStats => { - const { httpFetch } = useDataQualityContext(); +export const useStats = ({ + endDate, + pattern, + startDate, +}: { + endDate?: string | null; + pattern: string; + startDate?: string | null; +}): UseStats => { + const { httpFetch, isILMAvailable } = useDataQualityContext(); const [stats, setStats] = useState | null>(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); @@ -31,12 +40,22 @@ export const useStats = (pattern: string): UseStats => { async function fetchData() { try { const encodedIndexName = encodeURIComponent(`${pattern}`); + const query: HttpFetchQuery = { isILMAvailable }; + if (!isILMAvailable) { + if (startDate) { + query.startDate = startDate; + } + if (endDate) { + query.endDate = endDate; + } + } const response = await httpFetch>( `${STATS_ENDPOINT}/${encodedIndexName}`, { method: 'GET', signal: abortController.signal, + query, } ); @@ -59,7 +78,7 @@ export const useStats = (pattern: string): UseStats => { return () => { abortController.abort(); }; - }, [httpFetch, pattern, setError]); + }, [endDate, httpFetch, isILMAvailable, pattern, setError, startDate]); return { stats, error, loading }; }; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/index.test.tsx index b0d55edaf9129..b69de24cb6d9a 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/index.test.tsx @@ -25,7 +25,11 @@ const mockTelemetryEvents = { }; const ContextWrapper: React.FC = ({ children }) => ( - + {children} ); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/tsconfig.json b/x-pack/packages/security-solution/ecs_data_quality_dashboard/tsconfig.json index b033af7aa5a0c..4581552f2c591 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/tsconfig.json +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/tsconfig.json @@ -24,5 +24,6 @@ "@kbn/core-http-browser-mocks", "@kbn/elastic-assistant", "@kbn/triggers-actions-ui-plugin", + "@kbn/core", ] } diff --git a/x-pack/packages/security-solution/features/README.mdx b/x-pack/packages/security-solution/features/README.mdx new file mode 100644 index 0000000000000..e87fe71c4fac9 --- /dev/null +++ b/x-pack/packages/security-solution/features/README.mdx @@ -0,0 +1,4 @@ +## Security Solution App Features + +This package provides resources to be used for Security Solution app features + diff --git a/x-pack/packages/security-solution/features/app_features.ts b/x-pack/packages/security-solution/features/app_features.ts new file mode 100644 index 0000000000000..b9209441cff85 --- /dev/null +++ b/x-pack/packages/security-solution/features/app_features.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 { getSecurityFeature } from './src/security'; +export { getCasesFeature } from './src/cases'; +export { getAssistantFeature } from './src/assistant'; diff --git a/x-pack/packages/security-solution/features/config.ts b/x-pack/packages/security-solution/features/config.ts new file mode 100644 index 0000000000000..8f382fc13487f --- /dev/null +++ b/x-pack/packages/security-solution/features/config.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { securityDefaultAppFeaturesConfig } from './src/security/app_feature_config'; +export { getCasesDefaultAppFeaturesConfig } from './src/cases/app_feature_config'; +export { assistantDefaultAppFeaturesConfig } from './src/assistant/app_feature_config'; + +export { createEnabledAppFeaturesConfigMap } from './src/helpers'; diff --git a/x-pack/packages/security-solution/features/index.ts b/x-pack/packages/security-solution/features/index.ts new file mode 100644 index 0000000000000..a7fe0b5131c73 --- /dev/null +++ b/x-pack/packages/security-solution/features/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export * from './src/types'; diff --git a/x-pack/packages/security-solution/features/jest.config.js b/x-pack/packages/security-solution/features/jest.config.js new file mode 100644 index 0000000000000..47da21e7adff0 --- /dev/null +++ b/x-pack/packages/security-solution/features/jest.config.js @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/x-pack/packages/security-solution/features'], +}; diff --git a/x-pack/packages/security-solution/features/keys.ts b/x-pack/packages/security-solution/features/keys.ts new file mode 100644 index 0000000000000..11063c154567c --- /dev/null +++ b/x-pack/packages/security-solution/features/keys.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './src/app_features_keys'; diff --git a/x-pack/packages/security-solution/features/kibana.jsonc b/x-pack/packages/security-solution/features/kibana.jsonc new file mode 100644 index 0000000000000..0e5a360ea9929 --- /dev/null +++ b/x-pack/packages/security-solution/features/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/security-solution-features", + "owner": "@elastic/security-threat-hunting-explore" +} diff --git a/x-pack/packages/security-solution/features/package.json b/x-pack/packages/security-solution/features/package.json new file mode 100644 index 0000000000000..77abf87117eb8 --- /dev/null +++ b/x-pack/packages/security-solution/features/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/security-solution-features", + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0" +} \ No newline at end of file diff --git a/x-pack/packages/security-solution/features/privileges.ts b/x-pack/packages/security-solution/features/privileges.ts new file mode 100644 index 0000000000000..2e5a99095e4f5 --- /dev/null +++ b/x-pack/packages/security-solution/features/privileges.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export { AppFeaturesPrivilegeId, AppFeaturesPrivileges } from './src/app_features_privileges'; diff --git a/x-pack/plugins/security_solution/common/types/app_features.ts b/x-pack/packages/security-solution/features/src/app_features_keys.ts similarity index 64% rename from x-pack/plugins/security_solution/common/types/app_features.ts rename to x-pack/packages/security-solution/features/src/app_features_keys.ts index a8c65aeadfc8a..ea3939e2b9f28 100644 --- a/x-pack/plugins/security_solution/common/types/app_features.ts +++ b/x-pack/packages/security-solution/features/src/app_features_keys.ts @@ -6,60 +6,48 @@ */ export enum AppFeatureSecurityKey { - /** - * Enables Advanced Insights (Entity Risk, GenAI) - */ + /** Enables Advanced Insights (Entity Risk, GenAI) */ advancedInsights = 'advanced_insights', - /** * Enables Investigation guide in Timeline */ investigationGuide = 'investigation_guide', - /** * Enables access to the Endpoint List and associated views that allows management of hosts * running endpoint security */ endpointHostManagement = 'endpoint_host_management', - /** * Enables endpoint policy views that enables user to manage endpoint security policies */ endpointPolicyManagement = 'endpoint_policy_management', - /** * Enables Endpoint Policy protections (like Malware, Ransomware, etc) */ endpointPolicyProtections = 'endpoint_policy_protections', - /** * Enables management of all endpoint related artifacts (ex. Trusted Applications, Event Filters, * Host Isolation Exceptions, Blocklist. */ endpointArtifactManagement = 'endpoint_artifact_management', - /** * Enables all of endpoint's supported response actions - like host isolation, file operations, * process operations, command execution, etc. */ endpointResponseActions = 'endpoint_response_actions', - /** * Enables Threat Intelligence */ threatIntelligence = 'threat-intelligence', - /** * Enables Osquery Response Actions */ osqueryAutomatedResponseActions = 'osquery_automated_response_actions', -} -export enum AppFeatureAssistantKey { /** - * Enables Elastic AI Assistant + * Enables managing endpoint exceptions on rules and alerts */ - assistant = 'assistant', + endpointExceptions = 'endpointExceptions', } export enum AppFeatureCasesKey { @@ -69,14 +57,46 @@ export enum AppFeatureCasesKey { casesConnectors = 'cases_connectors', } -// Merges the two enums. -export type AppFeatureKey = AppFeatureSecurityKey | AppFeatureCasesKey | AppFeatureAssistantKey; -export type AppFeatureKeys = AppFeatureKey[]; +export enum AppFeatureAssistantKey { + /** + * Enables Elastic AI Assistant + */ + assistant = 'assistant', +} -// We need to merge the value and the type and export both to replicate how enum works. +// Merges the two enums. export const AppFeatureKey = { ...AppFeatureSecurityKey, ...AppFeatureCasesKey, ...AppFeatureAssistantKey, }; +// We need to merge the value and the type and export both to replicate how enum works. +export type AppFeatureKeyType = AppFeatureSecurityKey | AppFeatureCasesKey | AppFeatureAssistantKey; + export const ALL_APP_FEATURE_KEYS = Object.freeze(Object.values(AppFeatureKey)); + +/** Sub-features IDs for Security */ +export enum SecuritySubFeatureId { + endpointList = 'endpointListSubFeature', + endpointExceptions = 'endpointExceptionsSubFeature', + trustedApplications = 'trustedApplicationsSubFeature', + hostIsolationExceptions = 'hostIsolationExceptionsSubFeature', + blocklist = 'blocklistSubFeature', + eventFilters = 'eventFiltersSubFeature', + policyManagement = 'policyManagementSubFeature', + responseActionsHistory = 'responseActionsHistorySubFeature', + hostIsolation = 'hostIsolationSubFeature', + processOperations = 'processOperationsSubFeature', + fileOperations = 'fileOperationsSubFeature', + executeAction = 'executeActionSubFeature', +} + +/** Sub-features IDs for Cases */ +export enum CasesSubFeatureId { + deleteCases = 'deleteCasesSubFeature', +} + +/** Sub-features IDs for Security Assistant */ +export enum AssistantSubFeatureId { + createConversation = 'createConversationSubFeature', +} diff --git a/x-pack/packages/security-solution/features/src/app_features_privileges.ts b/x-pack/packages/security-solution/features/src/app_features_privileges.ts new file mode 100644 index 0000000000000..24fe0e25a19cc --- /dev/null +++ b/x-pack/packages/security-solution/features/src/app_features_privileges.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { APP_ID } from './constants'; + +export enum AppFeaturesPrivilegeId { + endpointExceptions = 'endpoint_exceptions', +} + +/** + * This is the mapping of the privileges that are registered + * using a different Kibana feature configuration (sub-feature, main feature privilege, etc) + * in each offering type (ess, serverless) + */ +export const AppFeaturesPrivileges = { + [AppFeaturesPrivilegeId.endpointExceptions]: { + all: { + ui: ['showEndpointExceptions', 'crudEndpointExceptions'], + api: [`${APP_ID}-showEndpointExceptions`, `${APP_ID}-crudEndpointExceptions`], + }, + read: { + ui: ['showEndpointExceptions'], + api: [`${APP_ID}-showEndpointExceptions`], + }, + }, +}; diff --git a/x-pack/packages/security-solution/features/src/assistant/app_feature_config.ts b/x-pack/packages/security-solution/features/src/assistant/app_feature_config.ts new file mode 100644 index 0000000000000..b55c43f82c953 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/assistant/app_feature_config.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 type { AssistantSubFeatureId } from '../app_features_keys'; +import { AppFeatureAssistantKey } from '../app_features_keys'; +import type { AppFeatureKibanaConfig } from '../types'; + +/** + * App features privileges configuration for the Security Assistant Kibana Feature app. + * These are the configs that are shared between both offering types (ess and serverless). + * They can be extended on each offering plugin to register privileges using different way on each offering type. + * + * Privileges can be added in different ways: + * - `privileges`: the privileges that will be added directly into the main Security feature. + * - `subFeatureIds`: the ids of the sub-features that will be added into the Security subFeatures entry. + * - `subFeaturesPrivileges`: the privileges that will be added into the existing Security subFeature with the privilege `id` specified. + */ +export const assistantDefaultAppFeaturesConfig: Record< + AppFeatureAssistantKey, + AppFeatureKibanaConfig +> = { + [AppFeatureAssistantKey.assistant]: { + privileges: { + all: { + ui: ['ai-assistant'], + }, + }, + }, +}; diff --git a/x-pack/packages/security-solution/features/src/assistant/index.ts b/x-pack/packages/security-solution/features/src/assistant/index.ts new file mode 100644 index 0000000000000..d1319fd637913 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/assistant/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { AssistantSubFeatureId } from '../app_features_keys'; +import type { AppFeatureParams } from '../types'; +import { getAssistantBaseKibanaFeature } from './kibana_features'; +import { + getAssistantBaseKibanaSubFeatureIds, + assistantSubFeaturesMap, +} from './kibana_sub_features'; + +export const getAssistantFeature = (): AppFeatureParams => ({ + baseKibanaFeature: getAssistantBaseKibanaFeature(), + baseKibanaSubFeatureIds: getAssistantBaseKibanaSubFeatureIds(), + subFeaturesMap: assistantSubFeaturesMap, +}); diff --git a/x-pack/packages/security-solution/features/src/assistant/kibana_features.ts b/x-pack/packages/security-solution/features/src/assistant/kibana_features.ts new file mode 100644 index 0000000000000..e04b1f44df739 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/assistant/kibana_features.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 { i18n } from '@kbn/i18n'; + +import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; +import { type BaseKibanaFeatureConfig } from '../types'; +import { APP_ID, ASSISTANT_FEATURE_ID } from '../constants'; + +export const getAssistantBaseKibanaFeature = (): BaseKibanaFeatureConfig => ({ + id: ASSISTANT_FEATURE_ID, + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.linkSecuritySolutionAssistantTitle', + { + defaultMessage: 'Elastic AI Assistant', + } + ), + order: 1100, + category: DEFAULT_APP_CATEGORIES.security, + app: [ASSISTANT_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + minimumLicense: 'enterprise', + privileges: { + all: { + api: [], + app: [ASSISTANT_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + savedObject: { + all: [], + read: [], + }, + ui: [], + }, + read: { + // No read-only mode currently supported + disabled: true, + savedObject: { + all: [], + read: [], + }, + ui: [], + }, + }, +}); diff --git a/x-pack/plugins/security_solution/server/lib/app_features/security_assistant_kibana_sub_features.ts b/x-pack/packages/security-solution/features/src/assistant/kibana_sub_features.ts similarity index 66% rename from x-pack/plugins/security_solution/server/lib/app_features/security_assistant_kibana_sub_features.ts rename to x-pack/packages/security-solution/features/src/assistant/kibana_sub_features.ts index bc495e8c24d60..253b98f602c92 100644 --- a/x-pack/plugins/security_solution/server/lib/app_features/security_assistant_kibana_sub_features.ts +++ b/x-pack/packages/security-solution/features/src/assistant/kibana_sub_features.ts @@ -12,13 +12,13 @@ import type { SubFeatureConfig } from '@kbn/features-plugin/common'; // @ts-expect-error unused variable const createConversationSubFeature: SubFeatureConfig = { name: i18n.translate( - 'xpack.securitySolution.featureRegistry.assistant.createConversationSubFeatureName', + 'securitySolutionPackages.features.featureRegistry.assistant.createConversationSubFeatureName', { defaultMessage: 'Create Conversations', } ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.assistant.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.assistant.description', { defaultMessage: 'Create custom conversations.' } ), privilegeGroups: [ @@ -29,7 +29,7 @@ const createConversationSubFeature: SubFeatureConfig = { api: [], id: 'create_conversation', name: i18n.translate( - 'xpack.securitySolution.featureRegistry.assistant.createConversationSubFeatureDetails', + 'securitySolutionPackages.features.featureRegistry.assistant.createConversationSubFeatureDetails', { defaultMessage: 'Create conversations', } @@ -50,7 +50,19 @@ export enum AssistantSubFeatureId { createConversation = 'createConversationSubFeature', } -// Defines all the ordered Security Assistant subFeatures available +/** + * Sub-features that will always be available for Security Assistant + * regardless of the product type. + */ +export const getAssistantBaseKibanaSubFeatureIds = (): AssistantSubFeatureId[] => [ + // This is a sample sub-feature that can be used for future implementations + // AssistantSubFeatureId.createConversation, +]; + +/** + * Defines all the Security Assistant subFeatures available. + * The order of the subFeatures is the order they will be displayed + */ export const assistantSubFeaturesMap = Object.freeze( new Map([ // This is a sample sub-feature that can be used for future implementations diff --git a/x-pack/packages/security-solution/features/src/cases/app_feature_config.ts b/x-pack/packages/security-solution/features/src/cases/app_feature_config.ts new file mode 100644 index 0000000000000..cfad7bfa7715d --- /dev/null +++ b/x-pack/packages/security-solution/features/src/cases/app_feature_config.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 { AppFeatureCasesKey } from '../app_features_keys'; +import { APP_ID } from '../constants'; +import type { DefaultCasesAppFeaturesConfig } from './types'; + +/** + * App features privileges configuration for the Security Cases Kibana Feature app. + * These are the configs that are shared between both offering types (ess and serverless). + * They can be extended on each offering plugin to register privileges using different way on each offering type. + * + * Privileges can be added in different ways: + * - `privileges`: the privileges that will be added directly into the main Security feature. + * - `subFeatureIds`: the ids of the sub-features that will be added into the Security subFeatures entry. + * - `subFeaturesPrivileges`: the privileges that will be added into the existing Security subFeature with the privilege `id` specified. + */ +export const getCasesDefaultAppFeaturesConfig = ({ + apiTags, + uiCapabilities, +}: { + apiTags: { connectors: string }; + uiCapabilities: { connectors: string }; +}): DefaultCasesAppFeaturesConfig => ({ + [AppFeatureCasesKey.casesConnectors]: { + privileges: { + all: { + api: [apiTags.connectors], + ui: [uiCapabilities.connectors], + cases: { + push: [APP_ID], + }, + }, + read: { + api: [apiTags.connectors], + ui: [uiCapabilities.connectors], + }, + }, + }, +}); diff --git a/x-pack/packages/security-solution/features/src/cases/index.ts b/x-pack/packages/security-solution/features/src/cases/index.ts new file mode 100644 index 0000000000000..dbc0355d36565 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/cases/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { CasesSubFeatureId } from '../app_features_keys'; +import type { AppFeatureParams } from '../types'; +import { getCasesBaseKibanaFeature } from './kibana_features'; +import { getCasesBaseKibanaSubFeatureIds, getCasesSubFeaturesMap } from './kibana_sub_features'; +import type { CasesFeatureParams } from './types'; + +export const getCasesFeature = ( + params: CasesFeatureParams +): AppFeatureParams => ({ + baseKibanaFeature: getCasesBaseKibanaFeature(params), + baseKibanaSubFeatureIds: getCasesBaseKibanaSubFeatureIds(), + subFeaturesMap: getCasesSubFeaturesMap(params), +}); diff --git a/x-pack/packages/security-solution/features/src/cases/kibana_features.ts b/x-pack/packages/security-solution/features/src/cases/kibana_features.ts new file mode 100644 index 0000000000000..a8da25bb6e40b --- /dev/null +++ b/x-pack/packages/security-solution/features/src/cases/kibana_features.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 { i18n } from '@kbn/i18n'; + +import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; +import type { BaseKibanaFeatureConfig } from '../types'; +import { APP_ID, CASES_FEATURE_ID } from '../constants'; +import type { CasesFeatureParams } from './types'; + +export const getCasesBaseKibanaFeature = ({ + uiCapabilities, + apiTags, + savedObjects, +}: CasesFeatureParams): BaseKibanaFeatureConfig => { + return { + id: CASES_FEATURE_ID, + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.linkSecuritySolutionCaseTitle', + { + defaultMessage: 'Cases', + } + ), + order: 1100, + category: DEFAULT_APP_CATEGORIES.security, + app: [CASES_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + cases: [APP_ID], + privileges: { + all: { + api: apiTags.all, + app: [CASES_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + cases: { + create: [APP_ID], + read: [APP_ID], + update: [APP_ID], + }, + savedObject: { + all: [...savedObjects.files], + read: [...savedObjects.files], + }, + ui: uiCapabilities.all, + }, + read: { + api: apiTags.read, + app: [CASES_FEATURE_ID, 'kibana'], + catalogue: [APP_ID], + cases: { + read: [APP_ID], + }, + savedObject: { + all: [], + read: [...savedObjects.files], + }, + ui: uiCapabilities.read, + }, + }, + }; +}; diff --git a/x-pack/packages/security-solution/features/src/cases/kibana_sub_features.ts b/x-pack/packages/security-solution/features/src/cases/kibana_sub_features.ts new file mode 100644 index 0000000000000..3cbdb3f0e9123 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/cases/kibana_sub_features.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 { i18n } from '@kbn/i18n'; +import type { SubFeatureConfig } from '@kbn/features-plugin/common'; +import { CasesSubFeatureId } from '../app_features_keys'; +import { APP_ID } from '../constants'; +import type { CasesFeatureParams } from './types'; + +/** + * Sub-features that will always be available for Security Cases + * regardless of the product type. + */ +export const getCasesBaseKibanaSubFeatureIds = (): CasesSubFeatureId[] => [ + CasesSubFeatureId.deleteCases, +]; + +/** + * Defines all the Security Assistant subFeatures available. + * The order of the subFeatures is the order they will be displayed + */ +export const getCasesSubFeaturesMap = ({ + uiCapabilities, + apiTags, + savedObjects, +}: CasesFeatureParams) => { + const deleteCasesSubFeature: SubFeatureConfig = { + name: i18n.translate('securitySolutionPackages.features.featureRegistry.deleteSubFeatureName', { + defaultMessage: 'Delete', + }), + privilegeGroups: [ + { + groupType: 'independent', + privileges: [ + { + api: apiTags.delete, + id: 'cases_delete', + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.deleteSubFeatureDetails', + { + defaultMessage: 'Delete cases and comments', + } + ), + includeIn: 'all', + savedObject: { + all: [...savedObjects.files], + read: [...savedObjects.files], + }, + cases: { + delete: [APP_ID], + }, + ui: uiCapabilities.delete, + }, + ], + }, + ], + }; + + return new Map([ + [CasesSubFeatureId.deleteCases, deleteCasesSubFeature], + ]); +}; diff --git a/x-pack/packages/security-solution/features/src/cases/types.ts b/x-pack/packages/security-solution/features/src/cases/types.ts new file mode 100644 index 0000000000000..b7c093b0cadc3 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/cases/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 type { CasesUiCapabilities, CasesApiTags } from '@kbn/cases-plugin/common'; +import type { AppFeatureCasesKey, CasesSubFeatureId } from '../app_features_keys'; +import type { AppFeatureKibanaConfig } from '../types'; + +export interface CasesFeatureParams { + uiCapabilities: CasesUiCapabilities; + apiTags: CasesApiTags; + savedObjects: { files: string[] }; +} + +export type DefaultCasesAppFeaturesConfig = Record< + AppFeatureCasesKey, + AppFeatureKibanaConfig +>; diff --git a/x-pack/packages/security-solution/features/src/constants.ts b/x-pack/packages/security-solution/features/src/constants.ts new file mode 100644 index 0000000000000..2054749d0eabb --- /dev/null +++ b/x-pack/packages/security-solution/features/src/constants.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. + */ + +// Same as the plugin id defined by Security Solution +export const APP_ID = 'securitySolution' as const; +export const SERVER_APP_ID = 'siem' as const; + +export const CASES_FEATURE_ID = 'securitySolutionCases' as const; +export const ASSISTANT_FEATURE_ID = 'securitySolutionAssistant' as const; + +// Same as the plugin id defined by Cloud Security Posture +export const CLOUD_POSTURE_APP_ID = 'csp' as const; + +/** + * Id for the notifications alerting type + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const LEGACY_NOTIFICATIONS_ID = `siem.notifications` as const; diff --git a/x-pack/packages/security-solution/features/src/helpers.ts b/x-pack/packages/security-solution/features/src/helpers.ts new file mode 100644 index 0000000000000..1beb8a3a6284c --- /dev/null +++ b/x-pack/packages/security-solution/features/src/helpers.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AppFeatureKeys, AppFeatureKeyType, AppFeatureKibanaConfig } from './types'; + +/** + * Creates the AppFeaturesConfig Map from the given appFeatures object and a set of enabled appFeatures keys. + */ +export const createEnabledAppFeaturesConfigMap = < + K extends AppFeatureKeyType, + T extends string = string +>( + appFeatures: Record>, + enabledAppFeaturesKeys: AppFeatureKeys +) => { + return new Map( + Object.entries>(appFeatures).reduce< + Array<[K, AppFeatureKibanaConfig]> + >((acc, [key, value]) => { + if (enabledAppFeaturesKeys.includes(key as K)) { + acc.push([key as K, value]); + } + return acc; + }, []) + ); +}; diff --git a/x-pack/packages/security-solution/features/src/security/app_feature_config.ts b/x-pack/packages/security-solution/features/src/security/app_feature_config.ts new file mode 100644 index 0000000000000..a27dccd6c5bf6 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/security/app_feature_config.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 { AppFeatureSecurityKey, SecuritySubFeatureId } from '../app_features_keys'; +import { APP_ID } from '../constants'; +import type { DefaultSecurityAppFeaturesConfig } from './types'; + +/** + * App features privileges configuration for the Security Solution Kibana Feature app. + * These are the configs that are shared between both offering types (ess and serverless). + * They can be extended on each offering plugin to register privileges using different way on each offering type. + * + * Privileges can be added in different ways: + * - `privileges`: the privileges that will be added directly into the main Security feature. + * - `subFeatureIds`: the ids of the sub-features that will be added into the Security subFeatures entry. + * - `subFeaturesPrivileges`: the privileges that will be added into the existing Security subFeature with the privilege `id` specified. + */ +export const securityDefaultAppFeaturesConfig: DefaultSecurityAppFeaturesConfig = { + [AppFeatureSecurityKey.advancedInsights]: { + privileges: { + all: { + ui: ['entity-analytics'], + api: [`${APP_ID}-entity-analytics`], + }, + read: { + ui: ['entity-analytics'], + api: [`${APP_ID}-entity-analytics`], + }, + }, + }, + [AppFeatureSecurityKey.investigationGuide]: { + privileges: { + all: { + ui: ['investigation-guide'], + }, + read: { + ui: ['investigation-guide'], + }, + }, + }, + + [AppFeatureSecurityKey.threatIntelligence]: { + privileges: { + all: { + ui: ['threat-intelligence'], + api: [`${APP_ID}-threat-intelligence`], + }, + read: { + ui: ['threat-intelligence'], + api: [`${APP_ID}-threat-intelligence`], + }, + }, + }, + + [AppFeatureSecurityKey.endpointHostManagement]: { + subFeatureIds: [SecuritySubFeatureId.endpointList], + }, + + [AppFeatureSecurityKey.endpointPolicyManagement]: { + subFeatureIds: [SecuritySubFeatureId.policyManagement], + }, + + // Adds no additional kibana feature controls + [AppFeatureSecurityKey.endpointPolicyProtections]: {}, + + [AppFeatureSecurityKey.endpointArtifactManagement]: { + subFeatureIds: [ + SecuritySubFeatureId.trustedApplications, + SecuritySubFeatureId.blocklist, + SecuritySubFeatureId.eventFilters, + ], + subFeaturesPrivileges: [ + { + id: 'host_isolation_exceptions_all', + api: [`${APP_ID}-accessHostIsolationExceptions`, `${APP_ID}-writeHostIsolationExceptions`], + ui: ['accessHostIsolationExceptions', 'writeHostIsolationExceptions'], + }, + { + id: 'host_isolation_exceptions_read', + api: [`${APP_ID}-accessHostIsolationExceptions`], + ui: ['accessHostIsolationExceptions'], + }, + ], + }, + + [AppFeatureSecurityKey.endpointResponseActions]: { + subFeatureIds: [ + SecuritySubFeatureId.hostIsolationExceptions, + SecuritySubFeatureId.responseActionsHistory, + SecuritySubFeatureId.hostIsolation, + SecuritySubFeatureId.processOperations, + SecuritySubFeatureId.fileOperations, + SecuritySubFeatureId.executeAction, + ], + subFeaturesPrivileges: [ + { + id: 'host_isolation_all', + api: [`${APP_ID}-writeHostIsolation`], + ui: ['writeHostIsolation'], + }, + ], + }, + + [AppFeatureSecurityKey.osqueryAutomatedResponseActions]: {}, +}; diff --git a/x-pack/packages/security-solution/features/src/security/index.ts b/x-pack/packages/security-solution/features/src/security/index.ts new file mode 100644 index 0000000000000..67f72361fb0cc --- /dev/null +++ b/x-pack/packages/security-solution/features/src/security/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { SecuritySubFeatureId } from '../app_features_keys'; +import type { AppFeatureParams } from '../types'; +import { getSecurityBaseKibanaFeature } from './kibana_features'; +import { securitySubFeaturesMap, getSecurityBaseKibanaSubFeatureIds } from './kibana_sub_features'; +import type { SecurityFeatureParams } from './types'; + +export const getSecurityFeature = ( + params: SecurityFeatureParams +): AppFeatureParams => ({ + baseKibanaFeature: getSecurityBaseKibanaFeature(params), + baseKibanaSubFeatureIds: getSecurityBaseKibanaSubFeatureIds(params), + subFeaturesMap: securitySubFeaturesMap, +}); diff --git a/x-pack/packages/security-solution/features/src/security/kibana_features.ts b/x-pack/packages/security-solution/features/src/security/kibana_features.ts new file mode 100644 index 0000000000000..34252ec1a35be --- /dev/null +++ b/x-pack/packages/security-solution/features/src/security/kibana_features.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 { i18n } from '@kbn/i18n'; + +import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; +import { + EQL_RULE_TYPE_ID, + INDICATOR_RULE_TYPE_ID, + ML_RULE_TYPE_ID, + NEW_TERMS_RULE_TYPE_ID, + QUERY_RULE_TYPE_ID, + SAVED_QUERY_RULE_TYPE_ID, + THRESHOLD_RULE_TYPE_ID, +} from '@kbn/securitysolution-rules'; +import type { BaseKibanaFeatureConfig } from '../types'; +import { APP_ID, SERVER_APP_ID, LEGACY_NOTIFICATIONS_ID, CLOUD_POSTURE_APP_ID } from '../constants'; +import type { SecurityFeatureParams } from './types'; + +const SECURITY_RULE_TYPES = [ + LEGACY_NOTIFICATIONS_ID, + EQL_RULE_TYPE_ID, + INDICATOR_RULE_TYPE_ID, + ML_RULE_TYPE_ID, + QUERY_RULE_TYPE_ID, + SAVED_QUERY_RULE_TYPE_ID, + THRESHOLD_RULE_TYPE_ID, + NEW_TERMS_RULE_TYPE_ID, +]; + +export const getSecurityBaseKibanaFeature = ({ + savedObjects, +}: SecurityFeatureParams): BaseKibanaFeatureConfig => ({ + id: SERVER_APP_ID, + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.linkSecuritySolutionTitle', + { + defaultMessage: 'Security', + } + ), + order: 1100, + category: DEFAULT_APP_CATEGORIES.security, + app: [APP_ID, CLOUD_POSTURE_APP_ID, 'kibana'], + catalogue: [APP_ID], + management: { + insightsAndAlerting: ['triggersActions'], + }, + alerting: SECURITY_RULE_TYPES, + privileges: { + all: { + app: [APP_ID, CLOUD_POSTURE_APP_ID, 'kibana'], + catalogue: [APP_ID], + api: [ + APP_ID, + 'lists-all', + 'lists-read', + 'lists-summary', + 'rac', + 'cloud-security-posture-all', + 'cloud-security-posture-read', + ], + savedObject: { + all: ['alert', ...savedObjects], + read: [], + }, + alerting: { + rule: { + all: SECURITY_RULE_TYPES, + }, + alert: { + all: SECURITY_RULE_TYPES, + }, + }, + management: { + insightsAndAlerting: ['triggersActions'], + }, + ui: ['show', 'crud'], + }, + read: { + app: [APP_ID, CLOUD_POSTURE_APP_ID, 'kibana'], + catalogue: [APP_ID], + api: [APP_ID, 'lists-read', 'rac', 'cloud-security-posture-read'], + savedObject: { + all: [], + read: [...savedObjects], + }, + alerting: { + rule: { + read: SECURITY_RULE_TYPES, + }, + alert: { + all: SECURITY_RULE_TYPES, + }, + }, + management: { + insightsAndAlerting: ['triggersActions'], + }, + ui: ['show'], + }, + }, +}); diff --git a/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_sub_features.ts b/x-pack/packages/security-solution/features/src/security/kibana_sub_features.ts similarity index 68% rename from x-pack/plugins/security_solution/server/lib/app_features/security_kibana_sub_features.ts rename to x-pack/packages/security-solution/features/src/security/kibana_sub_features.ts index a8410e4e4253d..86cbf89f26a6f 100644 --- a/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_sub_features.ts +++ b/x-pack/packages/security-solution/features/src/security/kibana_sub_features.ts @@ -8,21 +8,27 @@ import { i18n } from '@kbn/i18n'; import type { SubFeatureConfig } from '@kbn/features-plugin/common'; import { EXCEPTION_LIST_NAMESPACE_AGNOSTIC } from '@kbn/securitysolution-list-constants'; -import { APP_ID } from '../../../common'; +import { AppFeaturesPrivilegeId, AppFeaturesPrivileges } from '../app_features_privileges'; +import { SecuritySubFeatureId } from '../app_features_keys'; +import { APP_ID } from '../constants'; +import type { SecurityFeatureParams } from './types'; const endpointListSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.endpointList.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointList.privilegesTooltip', { defaultMessage: 'All Spaces is required for Endpoint List access.', } ), - name: i18n.translate('xpack.securitySolution.featureRegistry.subFeatures.endpointList', { - defaultMessage: 'Endpoint List', - }), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointList', + { + defaultMessage: 'Endpoint List', + } + ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.endpointList.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointList.description', { defaultMessage: 'Displays all hosts running Elastic Defend and their relevant integration details.', @@ -61,16 +67,19 @@ const endpointListSubFeature: SubFeatureConfig = { const trustedApplicationsSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.trustedApplications.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.privilegesTooltip', { defaultMessage: 'All Spaces is required for Trusted Applications access.', } ), - name: i18n.translate('xpack.securitySolution.featureRegistry.subFeatures.trustedApplications', { - defaultMessage: 'Trusted Applications', - }), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications', + { + defaultMessage: 'Trusted Applications', + } + ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.trustedApplications.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.description', { defaultMessage: 'Helps mitigate conflicts with other software, usually other antivirus or endpoint security applications.', @@ -115,19 +124,19 @@ const trustedApplicationsSubFeature: SubFeatureConfig = { const hostIsolationExceptionsSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.hostIsolationExceptions.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolationExceptions.privilegesTooltip', { defaultMessage: 'All Spaces is required for Host Isolation Exceptions access.', } ), name: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.hostIsolationExceptions', + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolationExceptions', { defaultMessage: 'Host Isolation Exceptions', } ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.hostIsolationExceptions.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolationExceptions.description', { defaultMessage: 'Add specific IP addresses that isolated hosts are still allowed to communicate with, even when isolated from the rest of the network.', @@ -172,16 +181,16 @@ const hostIsolationExceptionsSubFeature: SubFeatureConfig = { const blocklistSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.blockList.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.blockList.privilegesTooltip', { defaultMessage: 'All Spaces is required for Blocklist access.', } ), - name: i18n.translate('xpack.securitySolution.featureRegistry.subFeatures.blockList', { + name: i18n.translate('securitySolutionPackages.features.featureRegistry.subFeatures.blockList', { defaultMessage: 'Blocklist', }), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.blockList.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.blockList.description', { defaultMessage: 'Extend Elastic Defend’s protection against malicious processes and protect against potentially harmful applications.', @@ -226,16 +235,19 @@ const blocklistSubFeature: SubFeatureConfig = { const eventFiltersSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.eventFilters.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.eventFilters.privilegesTooltip', { defaultMessage: 'All Spaces is required for Event Filters access.', } ), - name: i18n.translate('xpack.securitySolution.featureRegistry.subFeatures.eventFilters', { - defaultMessage: 'Event Filters', - }), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.eventFilters', + { + defaultMessage: 'Event Filters', + } + ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.eventFilters.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.eventFilters.description', { defaultMessage: 'Filter out endpoint events that you do not need or want stored in Elasticsearch.', @@ -280,16 +292,19 @@ const eventFiltersSubFeature: SubFeatureConfig = { const policyManagementSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.policyManagement.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.policyManagement.privilegesTooltip', { defaultMessage: 'All Spaces is required for Policy Management access.', } ), - name: i18n.translate('xpack.securitySolution.featureRegistry.subFeatures.policyManagement', { - defaultMessage: 'Elastic Defend Policy Management', - }), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.policyManagement', + { + defaultMessage: 'Elastic Defend Policy Management', + } + ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.policyManagement.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.policyManagement.description', { defaultMessage: 'Access the Elastic Defend integration policy to configure protections, event collection, and advanced policy features.', @@ -329,19 +344,19 @@ const policyManagementSubFeature: SubFeatureConfig = { const responseActionsHistorySubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.responseActionsHistory.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.responseActionsHistory.privilegesTooltip', { defaultMessage: 'All Spaces is required for Response Actions History access.', } ), name: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.responseActionsHistory', + 'securitySolutionPackages.features.featureRegistry.subFeatures.responseActionsHistory', { defaultMessage: 'Response Actions History', } ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.responseActionsHistory.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.responseActionsHistory.description', { defaultMessage: 'Access the history of response actions performed on endpoints.', } @@ -379,16 +394,19 @@ const responseActionsHistorySubFeature: SubFeatureConfig = { const hostIsolationSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.hostIsolation.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolation.privilegesTooltip', { defaultMessage: 'All Spaces is required for Host Isolation access.', } ), - name: i18n.translate('xpack.securitySolution.featureRegistry.subFeatures.hostIsolation', { - defaultMessage: 'Host Isolation', - }), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolation', + { + defaultMessage: 'Host Isolation', + } + ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.hostIsolation.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolation.description', { defaultMessage: 'Perform the "isolate" and "release" response actions.' } ), privilegeGroups: [ @@ -396,6 +414,7 @@ const hostIsolationSubFeature: SubFeatureConfig = { groupType: 'mutually_exclusive', privileges: [ { + api: [`${APP_ID}-writeHostIsolationRelease`], id: 'host_isolation_all', includeIn: 'none', name: 'All', @@ -403,11 +422,6 @@ const hostIsolationSubFeature: SubFeatureConfig = { all: [], read: [], }, - // FYI: The current set of values below (`api`, `ui`) cover only `release` response action. - // There is a second set of values for API and UI that are added later if `endpointResponseActions` - // appFeature is enabled. Needed to ensure that in a downgrade of license condition, - // users are still able to un-isolate a host machine. - api: [`${APP_ID}-writeHostIsolationRelease`], ui: ['writeHostIsolationRelease'], }, ], @@ -418,16 +432,19 @@ const hostIsolationSubFeature: SubFeatureConfig = { const processOperationsSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.processOperations.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.processOperations.privilegesTooltip', { defaultMessage: 'All Spaces is required for Process Operations access.', } ), - name: i18n.translate('xpack.securitySolution.featureRegistry.subFeatures.processOperations', { - defaultMessage: 'Process Operations', - }), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.processOperations', + { + defaultMessage: 'Process Operations', + } + ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.processOperations.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.processOperations.description', { defaultMessage: 'Perform process-related response actions in the response console.', } @@ -454,16 +471,19 @@ const processOperationsSubFeature: SubFeatureConfig = { const fileOperationsSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.fileOperations.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.fileOperations.privilegesTooltip', { defaultMessage: 'All Spaces is required for File Operations access.', } ), - name: i18n.translate('xpack.securitySolution.featureRegistry.subFeatures.fileOperations', { - defaultMessage: 'File Operations', - }), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.fileOperations', + { + defaultMessage: 'File Operations', + } + ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.fileOperations.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.fileOperations.description', { defaultMessage: 'Perform file-related response actions in the response console.', } @@ -493,16 +513,19 @@ const fileOperationsSubFeature: SubFeatureConfig = { const executeActionSubFeature: SubFeatureConfig = { requireAllSpaces: true, privilegesTooltip: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.executeOperations.privilegesTooltip', + 'securitySolutionPackages.features.featureRegistry.subFeatures.executeOperations.privilegesTooltip', { defaultMessage: 'All Spaces is required for Execute Operations access.', } ), - name: i18n.translate('xpack.securitySolution.featureRegistry.subFeatures.executeOperations', { - defaultMessage: 'Execute Operations', - }), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.executeOperations', + { + defaultMessage: 'Execute Operations', + } + ), description: i18n.translate( - 'xpack.securitySolution.featureRegistry.subFeatures.executeOperations.description', + 'securitySolutionPackages.features.featureRegistry.subFeatures.executeOperations.description', { // TODO: Update this description before 8.8 FF defaultMessage: 'Perform script execution on the endpoint.', @@ -528,24 +551,71 @@ const executeActionSubFeature: SubFeatureConfig = { ], }; -export enum SecuritySubFeatureId { - endpointList = 'endpointListSubFeature', - trustedApplications = 'trustedApplicationsSubFeature', - hostIsolationExceptions = 'hostIsolationExceptionsSubFeature', - blocklist = 'blocklistSubFeature', - eventFilters = 'eventFiltersSubFeature', - policyManagement = 'policyManagementSubFeature', - responseActionsHistory = 'responseActionsHistorySubFeature', - hostIsolation = 'hostIsolationSubFeature', - processOperations = 'processOperationsSubFeature', - fileOperations = 'fileOperationsSubFeature', - executeAction = 'executeActionSubFeature', -} +const endpointExceptionsSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointExceptions.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Endpoint Exceptions access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointExceptions', + { + defaultMessage: 'Endpoint Exceptions', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointExceptions.description', + { + defaultMessage: 'Use Endpoint Exceptions (this is a test sub-feature).', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + id: 'endpoint_exceptions_all', + includeIn: 'all', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ...AppFeaturesPrivileges[AppFeaturesPrivilegeId.endpointExceptions].all, + }, + { + id: 'endpoint_exceptions_read', + includeIn: 'read', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ...AppFeaturesPrivileges[AppFeaturesPrivilegeId.endpointExceptions].read, + }, + ], + }, + ], +}; + +/** + * Sub-features that will always be available for Security + * regardless of the product type. + */ +export const getSecurityBaseKibanaSubFeatureIds = ( + { experimentalFeatures }: SecurityFeatureParams // currently un-used, but left here as a convenience for possible future use +): SecuritySubFeatureId[] => [SecuritySubFeatureId.hostIsolation]; -// Defines all the ordered Security subFeatures available +/** + * Defines all the Security Assistant subFeatures available. + * The order of the subFeatures is the order they will be displayed + */ export const securitySubFeaturesMap = Object.freeze( new Map([ [SecuritySubFeatureId.endpointList, endpointListSubFeature], + [SecuritySubFeatureId.endpointExceptions, endpointExceptionsSubFeature], [SecuritySubFeatureId.trustedApplications, trustedApplicationsSubFeature], [SecuritySubFeatureId.hostIsolationExceptions, hostIsolationExceptionsSubFeature], [SecuritySubFeatureId.blocklist, blocklistSubFeature], diff --git a/x-pack/packages/security-solution/features/src/security/types.ts b/x-pack/packages/security-solution/features/src/security/types.ts new file mode 100644 index 0000000000000..4c2fee865ecd2 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/security/types.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AppFeatureSecurityKey, SecuritySubFeatureId } from '../app_features_keys'; +import type { AppFeatureKibanaConfig } from '../types'; + +export interface SecurityFeatureParams { + experimentalFeatures: Record; + savedObjects: string[]; +} + +export type DefaultSecurityAppFeaturesConfig = Omit< + Record>, + AppFeatureSecurityKey.endpointExceptions + // | add not default security app features here +>; diff --git a/x-pack/packages/security-solution/features/src/types.ts b/x-pack/packages/security-solution/features/src/types.ts new file mode 100644 index 0000000000000..825e2e8e4c3b2 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/types.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { + KibanaFeatureConfig, + SubFeatureConfig, + SubFeaturePrivilegeConfig, +} from '@kbn/features-plugin/common'; +import type { RecursivePartial } from '@kbn/utility-types'; +import type { + AppFeatureAssistantKey, + AppFeatureCasesKey, + AppFeatureKeyType, + AppFeatureSecurityKey, + AssistantSubFeatureId, + CasesSubFeatureId, + SecuritySubFeatureId, +} from './app_features_keys'; + +export type { AppFeatureKeyType }; +export type AppFeatureKeys = AppFeatureKeyType[]; + +// Features types +export type BaseKibanaFeatureConfig = Omit; +export type SubFeaturesPrivileges = RecursivePartial; +export type AppFeatureKibanaConfig = + RecursivePartial & { + subFeatureIds?: T[]; + subFeaturesPrivileges?: SubFeaturesPrivileges[]; + }; +export type AppFeaturesConfig = Map< + AppFeatureKeyType, + AppFeatureKibanaConfig +>; + +export type AppFeaturesSecurityConfig = Map< + AppFeatureSecurityKey, + AppFeatureKibanaConfig +>; +export type AppFeaturesCasesConfig = Map< + AppFeatureCasesKey, + AppFeatureKibanaConfig +>; + +export type AppFeaturesAssistantConfig = Map< + AppFeatureAssistantKey, + AppFeatureKibanaConfig +>; + +export type AppSubFeaturesMap = Map; + +export interface AppFeatureParams { + baseKibanaFeature: BaseKibanaFeatureConfig; + baseKibanaSubFeatureIds: T[]; + subFeaturesMap: AppSubFeaturesMap; +} diff --git a/x-pack/packages/security-solution/features/tsconfig.json b/x-pack/packages/security-solution/features/tsconfig.json new file mode 100644 index 0000000000000..2c153f831721d --- /dev/null +++ b/x-pack/packages/security-solution/features/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react", + ] + }, + "include": ["**/*.ts", "**/*.tsx"], + "kbn_references": [ + "@kbn/features-plugin", + "@kbn/utility-types", + "@kbn/i18n", + "@kbn/core-application-common", + "@kbn/cases-plugin", + "@kbn/securitysolution-rules", + "@kbn/securitysolution-list-constants", + ], + "exclude": ["target/**/*"] +} diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.tsx index b81b25144fcd0..f2b8247840cac 100644 --- a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.tsx +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.tsx @@ -81,9 +81,7 @@ export const LandingLinkIcon: React.FC = React.memo(functi
    - - {description} - + {description} {children}
    diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.tsx index 18c8ef07c10cb..20caecd5a4e2c 100644 --- a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.tsx +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.tsx @@ -89,7 +89,7 @@ export const LandingLinksImages: React.FC = React.memo( {isBeta && }
    - + {description} diff --git a/x-pack/performance/journeys/tags_listing_page.ts b/x-pack/performance/journeys/tags_listing_page.ts new file mode 100644 index 0000000000000..c102c2a68b9fd --- /dev/null +++ b/x-pack/performance/journeys/tags_listing_page.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 { Journey } from '@kbn/journeys'; +import { subj } from '@kbn/test-subj-selector'; + +const TAG_NAME = 'testing'; +const TAG_DESCRIPTION = 'test description'; + +export const journey = new Journey({ + esArchives: ['x-pack/performance/es_archives/sample_data_flights'], + kbnArchives: ['x-pack/performance/kbn_archives/many_tags_and_visualizations'], +}) + .step('Go to Tags Page', async ({ page, kbnUrl }) => { + await page.goto(kbnUrl.get(`/app/management/kibana/tags`)); + await page.waitForSelector(subj('tagsManagementTable table-is-ready')); + }) + .step('Delete the first 20 tags', async ({ page }) => { + await page.click(subj('checkboxSelectAll')); + await page.click(subj('actionBar-contextMenuButton')); + await page.click(subj('actionBar-button-delete')); + await page.click(subj('confirmModalConfirmButton')); + await page.waitForSelector(subj('tagsManagementTable table-is-ready')); + }) + .step(`Search for 'stream' tag`, async ({ page, inputDelays }) => { + await page.type(subj('tagsManagementSearchBar'), 'stream', { + delay: inputDelays.TYPING, + }); + await page.waitForSelector(subj('tagsManagementTable table-is-ready')); + }) + .step('Create a new tag', async ({ page, inputDelays, kibanaPage }) => { + await kibanaPage.clearInput(subj('tagsManagementSearchBar')); + await page.waitForSelector(subj('tagsManagementTable table-is-ready')); + await page.click(subj('createTagButton')); + await page.type(subj('createModalField-name'), TAG_NAME, { delay: inputDelays.TYPING }); + await kibanaPage.clickAndWaitFor(subj('createModalConfirmButton'), 'detached'); + await page.waitForSelector(subj('tagsManagementTable table-is-ready')); + // search for newly created tag + await page.type(subj('tagsManagementSearchBar'), TAG_NAME, { + delay: inputDelays.TYPING, + }); + await page.waitForSelector(subj('tagsManagementTable table-is-ready')); + await page.waitForSelector(subj('tagsTableRowName'), { state: 'visible' }); + }) + .step('Update tag', async ({ page, inputDelays, kibanaPage }) => { + await page.click(subj('tagsTableAction-edit')); + await page.type(subj('createModalField-description'), TAG_DESCRIPTION, { + delay: inputDelays.TYPING, + }); + await kibanaPage.clickAndWaitFor(subj('createModalConfirmButton'), 'detached'); + await page.waitForSelector(subj('tagsManagementTable table-is-ready')); + }) + .step('Delete tag', async ({ page }) => { + const tagRow = page.locator(subj('tagsTableRowName')); + await page.click(subj('euiCollapsedItemActionsButton')); + await page.click(subj('tagsTableAction-delete')); + await page.click(subj('confirmModalConfirmButton')); + await page.waitForSelector(subj('tagsManagementTable table-is-ready')); + await tagRow.waitFor({ state: 'detached' }); + }); diff --git a/x-pack/performance/kbn_archives/many_tags_and_visualizations.json b/x-pack/performance/kbn_archives/many_tags_and_visualizations.json new file mode 100644 index 0000000000000..b2b53b6662b5a --- /dev/null +++ b/x-pack/performance/kbn_archives/many_tags_and_visualizations.json @@ -0,0 +1,5848 @@ +{ + "attributes": { + "color": "#c4ed81", + "description": "", + "name": "pipelines" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:45:24.903Z", + "id": "01a24370-3c22-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182724903, + 61 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:45:24.903Z", + "version": "WzEyNSwxXQ==" +} + +{ + "attributes": { + "color": "#08f5ad", + "description": "", + "name": "tsvb" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:47:09.060Z", + "id": "03402c40-3c33-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692190029060, + 229 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:47:09.060Z", + "version": "Wzg3NSwxXQ==" +} + +{ + "attributes": { + "color": "#39c978", + "description": "", + "name": "delay" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:55:10.362Z", + "id": "5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183310362, + 79 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:55:10.362Z", + "version": "WzE1MiwxXQ==" +} + +{ + "attributes": { + "color": "#bb6c5e", + "description": "", + "name": "flights" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:30:28.413Z", + "id": "eb48bed0-3c1f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181828413, + 17 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:30:28.413Z", + "version": "WzUwLDFd" +} + +{ + "attributes": { + "color": "#33570e", + "description": "", + "name": "destination" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:40:50.428Z", + "id": "219183c0-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692189650428, + 188 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:40:50.428Z", + "version": "WzczNiwxXQ==" +} + +{ + "attributes": { + "fieldFormatMap": "{\"hour_of_day\":{\"id\":\"number\",\"params\":{\"pattern\":\"00\"}},\"AvgTicketPrice\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.[00]\"}}}", + "name": "Kibana Sample Data Flights", + "runtimeFieldMap": "{\"hour_of_day\":{\"type\":\"long\",\"script\":{\"source\":\"emit(doc['timestamp'].value.getHour());\"}}}", + "timeFieldName": "timestamp", + "title": "kibana_sample_data_flights" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:26:07.159Z", + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "managed": false, + "references": [], + "sort": [ + 1692188767159, + 4294967296 + ], + "type": "index-pattern", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:26:07.159Z", + "version": "Wzc2LDFd" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "[Flights] Delays & Cancellations #2", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"aggs\":[],\"params\":{\"annotations\":[{\"color\":\"rgba(0,98,177,1)\",\"fields\":\"FlightDelay,Cancelled,Carrier\",\"icon\":\"fa-exclamation-triangle\",\"id\":\"53b7dff0-4c89-11e8-a66a-6989ad5a0a39\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1,\"query_string\":{\"language\":\"lucene\",\"query\":\"FlightDelay:true AND Cancelled:true\"},\"template\":\"{{Carrier}}: Flight Delayed and Cancelled!\",\"time_field\":\"timestamp\",\"index_pattern_ref_name\":\"metrics_1_index_pattern\"}],\"axis_formatter\":\"number\",\"axis_max\":\"1\",\"axis_position\":\"left\",\"axis_scale\":\"normal\",\"drop_last_bucket\":0,\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"interval\":\">=1h\",\"isModelInvalid\":false,\"legend_position\":\"bottom\",\"max_lines_legend\":1,\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"rgba(0,156,224,1)\",\"fill\":0.5,\"formatter\":\"percent\",\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"label\":\"Percent Delays\",\"line_width\":\"2\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"numerator\":{\"language\":\"lucene\",\"query\":\"FlightDelay:true\"},\"type\":\"filter_ratio\"}],\"point_size\":\"0\",\"separate_axis\":0,\"split_color_mode\":\"gradient\",\"split_mode\":\"everything\",\"stacked\":\"none\",\"time_range_mode\":\"entire_time_range\"},{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"default\",\"id\":\"e30a52c0-3c32-11ee-8296-3fee16600ac1\",\"label\":\"\",\"line_width\":1,\"metrics\":[{\"field\":\"FlightDelayMin\",\"id\":\"e30a52c1-3c32-11ee-8296-3fee16600ac1\",\"type\":\"cardinality\"}],\"override_index_pattern\":0,\"palette\":{\"name\":\"default\",\"type\":\"palette\"},\"point_size\":1,\"separate_axis\":0,\"series_drop_last_bucket\":0,\"split_mode\":\"terms\",\"stacked\":\"none\",\"terms_field\":\"AvgTicketPrice\"}],\"show_grid\":1,\"show_legend\":0,\"time_field\":\"timestamp\",\"time_range_mode\":\"entire_time_range\",\"tooltip_mode\":\"show_all\",\"truncate_legend\":1,\"type\":\"timeseries\",\"use_kibana_indexes\":true,\"index_pattern_ref_name\":\"metrics_0_index_pattern\"},\"title\":\"[Flights] Delays & Cancellations #2\",\"type\":\"metrics\"}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:47:19.838Z", + "id": "09acc3e0-3c33-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "eb48bed0-3c1f-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-eb48bed0-3c1f-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "03402c40-3c33-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-03402c40-3c33-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "219183c0-3c32-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-219183c0-3c32-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "metrics_0_index_pattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "metrics_1_index_pattern", + "type": "index-pattern" + } + ], + "sort": [ + 1692190039838, + 4294967421 + ], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2023-08-16T12:47:19.838Z", + "version": "WzEzOCwxXQ==" +} + +{ + "attributes": { + "color": "#16f16c", + "description": "", + "name": "rules" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:45:38.997Z", + "id": "0a08d650-3c22-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182738997, + 64 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:45:38.997Z", + "version": "WzEyNiwxXQ==" +} + +{ + "attributes": { + "color": "#33c6b7", + "description": "", + "name": "cases" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:45:44.391Z", + "id": "0d3fe570-3c22-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182744391, + 65 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:45:44.391Z", + "version": "WzEyNywxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "e52bf9e1-21bf-478e-ad85-2d43a775ba53": { + "columnOrder": [ + "188582f5-ab1c-437b-adaf-f9505f2c1b8a", + "9c9d8820-36b4-45d4-b0b0-ee548816ab03" + ], + "columns": { + "188582f5-ab1c-437b-adaf-f9505f2c1b8a": { + "dataType": "string", + "isBucketed": true, + "label": "Top 10 values of DestCountry", + "operationType": "terms", + "params": { + "accuracyMode": true, + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "9c9d8820-36b4-45d4-b0b0-ee548816ab03", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "DestCountry" + }, + "9c9d8820-36b4-45d4-b0b0-ee548816ab03": { + "dataType": "number", + "isBucketed": false, + "label": "Sum of DistanceMiles", + "operationType": "sum", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "DistanceMiles" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "emsField": "iso2", + "emsLayerId": "world_countries", + "layerId": "e52bf9e1-21bf-478e-ad85-2d43a775ba53", + "regionAccessor": "188582f5-ab1c-437b-adaf-f9505f2c1b8a", + "valueAccessor": "9c9d8820-36b4-45d4-b0b0-ee548816ab03" + } + }, + "title": "Top Destanations - Region map", + "visualizationType": "lnsChoropleth" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:27:55.279Z", + "id": "126a2620-3c2f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-e52bf9e1-21bf-478e-ad85-2d43a775ba53", + "type": "index-pattern" + } + ], + "sort": [ + 1692188875279, + 4294967355 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:27:55.279Z", + "version": "Wzg2LDFd" +} + +{ + "attributes": { + "color": "#6eea70", + "description": "", + "name": "connector" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:45:53.696Z", + "id": "12cbba00-3c22-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182753696, + 62 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:45:53.696Z", + "version": "WzEzMCwxXQ==" +} + +{ + "attributes": { + "color": "#1bfb93", + "description": "", + "name": "connection" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:31:38.083Z", + "id": "14cf8b30-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181898083, + 19 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:31:38.083Z", + "version": "WzU5LDFd" +} + +{ + "attributes": { + "color": "#fc3275", + "description": "", + "name": "weather" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:40:33.099Z", + "id": "173d51b0-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692189633099, + 186 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:40:33.099Z", + "version": "WzcyOCwxXQ==" +} + +{ + "attributes": { + "color": "#3f2c24", + "description": "", + "name": "work" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:31:46.002Z", + "id": "1987e320-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181906002, + 24 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:31:46.002Z", + "version": "WzYwLDFd" +} + +{ + "attributes": { + "color": "#00cf01", + "description": "", + "name": "origin" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:40:42.577Z", + "id": "1ce38c10-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692189642577, + 187 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:40:42.577Z", + "version": "WzcyOSwxXQ==" +} + +{ + "attributes": { + "color": "#d2cf78", + "description": "", + "name": "vacation" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:31:54.453Z", + "id": "1e916850-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181914453, + 20 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:31:54.453Z", + "version": "WzYxLDFd" +} + +{ + "attributes": { + "color": "#95253f", + "description": "", + "name": "space" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:53:23.951Z", + "id": "1f2b2ff0-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183203951, + 66 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:53:23.951Z", + "version": "WzEzNiwxXQ==" +} + +{ + "attributes": { + "color": "#339662", + "description": "", + "name": "spaces" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:53:28.504Z", + "id": "21e1eb80-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183208504, + 67 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:53:28.504Z", + "version": "WzEzOCwxXQ==" +} + +{ + "attributes": { + "color": "#901fd9", + "description": "", + "name": "security" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:32:04.179Z", + "id": "245d7a30-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181924179, + 21 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:32:04.179Z", + "version": "WzY0LDFd" +} + +{ + "attributes": { + "color": "#19391d", + "description": "", + "name": "saved objects" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:53:37.463Z", + "id": "2738f470-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183217463, + 68 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:53:37.463Z", + "version": "WzEzOSwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "[Flights] Destination Weather", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"[Flights] Destination Weather\",\"type\":\"tagcloud\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"DestWeather\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"segment\"}],\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":12,\"maxFontSize\":46,\"showLabel\":false,\"palette\":{\"type\":\"palette\",\"name\":\"temperature\"}}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:26:07.159Z", + "id": "293b5a30-4c8f-11e8-b3d7-01146121b73d", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "sort": [ + 1692188767159, + 4294967306 + ], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2023-08-16T12:26:07.159Z", + "version": "WzgwLDFd" +} + +{ + "attributes": { + "color": "#dd1f3c", + "description": "", + "name": "search" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:32:13.777Z", + "id": "2a160410-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181933777, + 23 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:32:13.777Z", + "version": "WzY1LDFd" +} + +{ + "attributes": { + "color": "#ec03a6", + "description": "", + "name": "airport" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T11:09:33.411Z", + "id": "61030b30-3c25-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692184173411, + 88 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T11:09:33.411Z", + "version": "WzE2NiwxXQ==" +} + +{ + "attributes": { + "color": "#1b3568", + "description": "", + "name": "watcher" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:44:15.500Z", + "id": "d84434c0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182655500, + 52 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:44:15.500Z", + "version": "WzExMiwxXQ==" +} + +{ + "attributes": { + "color": "#342118", + "description": "", + "name": "report" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:40:06.236Z", + "id": "43b189c0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182406236, + 28 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:40:06.236Z", + "version": "Wzg0LDFd" +} + +{ + "attributes": { + "color": "#fc3655", + "description": "", + "name": "monitoring" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:35:35.475Z", + "id": "a24eb030-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182135475, + 26 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:35:35.475Z", + "version": "WzczLDFd" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "93d4f467-cd2a-438d-bf82-0d89d3594375": { + "columnOrder": [ + "db222e35-2792-4c1f-b8de-a4d8a2c022ee", + "720787a2-a250-4c41-a014-3bb8d3736454", + "db262b33-970d-40b5-9f59-d51d182d8849" + ], + "columns": { + "720787a2-a250-4c41-a014-3bb8d3736454": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "DestWeather", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "db262b33-970d-40b5-9f59-d51d182d8849", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "DestWeather" + }, + "db222e35-2792-4c1f-b8de-a4d8a2c022ee": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "OriginWeather", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "db262b33-970d-40b5-9f59-d51d182d8849", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "OriginWeather" + }, + "db262b33-970d-40b5-9f59-d51d182d8849": { + "dataType": "number", + "isBucketed": false, + "label": "Median of dayOfWeek", + "operationType": "median", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "dayOfWeek" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "gridConfig": { + "isCellLabelVisible": false, + "isXAxisLabelVisible": true, + "isXAxisTitleVisible": false, + "isYAxisLabelVisible": true, + "isYAxisTitleVisible": false, + "type": "heatmap_grid" + }, + "layerId": "93d4f467-cd2a-438d-bf82-0d89d3594375", + "layerType": "data", + "legend": { + "isVisible": true, + "position": "right", + "type": "heatmap_legend" + }, + "shape": "heatmap", + "valueAccessor": "db262b33-970d-40b5-9f59-d51d182d8849", + "xAccessor": "db222e35-2792-4c1f-b8de-a4d8a2c022ee", + "yAccessor": "720787a2-a250-4c41-a014-3bb8d3736454" + } + }, + "title": "Weather #2", + "visualizationType": "lnsHeatmap" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:41:50.178Z", + "id": "2c27c7e0-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-93d4f467-cd2a-438d-bf82-0d89d3594375", + "type": "index-pattern" + }, + { + "id": "61030b30-3c25-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-61030b30-3c25-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "d84434c0-3c21-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-d84434c0-3c21-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "43b189c0-3c21-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-43b189c0-3c21-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "219183c0-3c32-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-219183c0-3c32-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "a24eb030-3c20-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-a24eb030-3c20-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692189710178, + 4294967385 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:41:50.178Z", + "version": "WzExNiwxXQ==" +} + +{ + "attributes": { + "color": "#f0cfaa", + "description": "", + "name": "api keys" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:53:47.967Z", + "id": "2d7bbcf0-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183227967, + 71 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:53:47.967Z", + "version": "WzE0MCwxXQ==" +} + +{ + "attributes": { + "color": "#c103d0", + "description": "", + "name": "searching" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T11:08:07.795Z", + "id": "2dfb1430-3c25-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692184087795, + 78 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T11:08:07.795Z", + "version": "WzE1OCwxXQ==" +} + +{ + "attributes": { + "color": "#b3cc0b", + "description": "", + "name": "cloud" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T11:08:47.919Z", + "id": "45e583f0-3c25-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692184127919, + 86 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T11:08:47.919Z", + "version": "WzE2MiwxXQ==" +} + +{ + "attributes": { + "color": "#0c9297", + "description": "", + "name": "stream" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:54:19.383Z", + "id": "40357070-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183259383, + 72 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:54:19.383Z", + "version": "WzE0NCwxXQ==" +} + +{ + "attributes": { + "color": "#ce9bae", + "description": "", + "name": "demo" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:54:09.499Z", + "id": "3a5142b0-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183249499, + 75 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:54:09.499Z", + "version": "WzE0MiwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "3be92f0c-b6e0-4bb1-b68f-51b8a9924b2a": { + "columnOrder": [ + "4d394c6e-f469-4e14-8913-311ba8ed72e4", + "a77fab82-4ef6-42c1-8959-29f35b1ee7bd", + "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f" + ], + "columns": { + "4d394c6e-f469-4e14-8913-311ba8ed72e4": { + "dataType": "string", + "isBucketed": true, + "label": "Top 10 values of FlightNum", + "operationType": "terms", + "params": { + "accuracyMode": true, + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "FlightNum" + }, + "a77fab82-4ef6-42c1-8959-29f35b1ee7bd": { + "dataType": "string", + "isBucketed": true, + "label": "Top 3 values of Origin", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "Origin" + }, + "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f": { + "dataType": "number", + "isBucketed": false, + "label": "Unique count of FlightDelayType", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "FlightDelayType" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "layerId": "3be92f0c-b6e0-4bb1-b68f-51b8a9924b2a", + "layerType": "data", + "legendDisplay": "default", + "metrics": [ + "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "4d394c6e-f469-4e14-8913-311ba8ed72e4", + "a77fab82-4ef6-42c1-8959-29f35b1ee7bd" + ] + } + ], + "shape": "treemap" + } + }, + "title": "Delays", + "visualizationType": "lnsPie" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:34:05.598Z", + "id": "30455be0-3c31-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-3be92f0c-b6e0-4bb1-b68f-51b8a9924b2a", + "type": "index-pattern" + }, + { + "id": "61030b30-3c25-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-61030b30-3c25-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "45e583f0-3c25-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-45e583f0-3c25-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "40357070-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-40357070-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "3a5142b0-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-3a5142b0-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "2738f470-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-2738f470-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692189245598, + 4294967363 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:34:05.598Z", + "version": "WzEwMSwxXQ==" +} + +{ + "attributes": { + "color": "#0e61de", + "description": "", + "name": "research" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T11:08:21.115Z", + "id": "35eb8cb0-3c25-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692184101115, + 84 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T11:08:21.115Z", + "version": "WzE1OSwxXQ==" +} + +{ + "attributes": { + "color": "#8380f5", + "description": "", + "name": "settings" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:54:06.326Z", + "id": "386d1960-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183246326, + 70 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:54:06.326Z", + "version": "WzE0MSwxXQ==" +} + +{ + "attributes": { + "color": "#c714e7", + "description": "", + "name": "live" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:54:14.725Z", + "id": "3d6eaf50-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183254725, + 76 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:54:14.725Z", + "version": "WzE0MywxXQ==" +} + +{ + "attributes": { + "color": "#005dd3", + "description": "", + "name": "files" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:54:23.706Z", + "id": "42c913a0-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183263706, + 73 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:54:23.706Z", + "version": "WzE0NSwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "e52bf9e1-21bf-478e-ad85-2d43a775ba53": { + "columnOrder": [ + "188582f5-ab1c-437b-adaf-f9505f2c1b8a", + "9c9d8820-36b4-45d4-b0b0-ee548816ab03" + ], + "columns": { + "188582f5-ab1c-437b-adaf-f9505f2c1b8a": { + "dataType": "string", + "isBucketed": true, + "label": "Top 10 values of DestCountry", + "operationType": "terms", + "params": { + "accuracyMode": true, + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "9c9d8820-36b4-45d4-b0b0-ee548816ab03", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "DestCountry" + }, + "9c9d8820-36b4-45d4-b0b0-ee548816ab03": { + "dataType": "number", + "isBucketed": false, + "label": "Sum of DistanceMiles", + "operationType": "sum", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "DistanceMiles" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "layerId": "e52bf9e1-21bf-478e-ad85-2d43a775ba53", + "layerType": "data", + "legendDisplay": "default", + "metrics": [ + "9c9d8820-36b4-45d4-b0b0-ee548816ab03" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "188582f5-ab1c-437b-adaf-f9505f2c1b8a" + ] + } + ], + "shape": "donut" + } + }, + "title": "Top Destinations - Donut", + "visualizationType": "lnsPie" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:45:40.633Z", + "id": "46d44fc0-3c30-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-e52bf9e1-21bf-478e-ad85-2d43a775ba53", + "type": "index-pattern" + } + ], + "sort": [ + 1692189940633, + 4294967414 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:45:40.633Z", + "version": "WzEyOSwxXQ==" +} + +{ + "attributes": { + "color": "#065d60", + "description": "", + "name": "create" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:40:13.861Z", + "id": "483cde40-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182413861, + 33 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:40:13.861Z", + "version": "Wzg1LDFd" +} + +{ + "attributes": { + "color": "#170cac", + "description": "", + "name": "delete" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:40:18.282Z", + "id": "4adf9ca0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182418282, + 34 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:40:18.282Z", + "version": "Wzg2LDFd" +} + +{ + "attributes": { + "color": "#4fb458", + "description": "", + "name": "management" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:54:37.437Z", + "id": "4af842d0-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183277437, + 69 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:54:37.437Z", + "version": "WzE0NiwxXQ==" +} + +{ + "attributes": { + "color": "#f21529", + "description": "", + "name": "data views" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T11:08:57.834Z", + "id": "4bce6ca0-3c25-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692184137834, + 85 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T11:08:57.834Z", + "version": "WzE2MywxXQ==" +} + +{ + "attributes": { + "color": "#516319", + "description": "", + "name": "session" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:40:23.258Z", + "id": "4dd6e3a0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182423258, + 35 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:40:23.258Z", + "version": "Wzg3LDFd" +} + +{ + "attributes": { + "color": "#1d6a82", + "description": "", + "name": "cancelled" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:49:14.229Z", + "id": "4ddb7250-3c33-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692190154229, + 231 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:49:14.229Z", + "version": "Wzg5OCwxXQ==" +} + +{ + "attributes": { + "color": "#656216", + "description": "", + "name": "data" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:29:01.427Z", + "id": "b76fbc30-3c1f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181741427, + 12 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:29:01.427Z", + "version": "WzM2LDFd" +} + +{ + "attributes": { + "color": "#710c28", + "description": "", + "name": "logs" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:28:56.459Z", + "id": "b479adb0-3c1f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181736459, + 14 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:28:56.459Z", + "version": "WzI4LDFd" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "3be92f0c-b6e0-4bb1-b68f-51b8a9924b2a": { + "columnOrder": [ + "4d394c6e-f469-4e14-8913-311ba8ed72e4", + "a77fab82-4ef6-42c1-8959-29f35b1ee7bd", + "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f" + ], + "columns": { + "4d394c6e-f469-4e14-8913-311ba8ed72e4": { + "dataType": "string", + "isBucketed": true, + "label": "Top 10 values of FlightNum", + "operationType": "terms", + "params": { + "accuracyMode": true, + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "FlightNum" + }, + "a77fab82-4ef6-42c1-8959-29f35b1ee7bd": { + "dataType": "string", + "isBucketed": true, + "label": "Top 3 values of Origin", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "Origin" + }, + "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f": { + "dataType": "number", + "isBucketed": false, + "label": "Unique count of FlightDelayType", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "FlightDelayType" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "layerId": "3be92f0c-b6e0-4bb1-b68f-51b8a9924b2a", + "layerType": "data", + "legendDisplay": "default", + "metrics": [ + "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "4d394c6e-f469-4e14-8913-311ba8ed72e4", + "a77fab82-4ef6-42c1-8959-29f35b1ee7bd" + ] + } + ], + "shape": "pie" + } + }, + "title": "Delays #2", + "visualizationType": "lnsPie" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:34:55.754Z", + "id": "4e2a8ea0-3c31-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-3be92f0c-b6e0-4bb1-b68f-51b8a9924b2a", + "type": "index-pattern" + }, + { + "id": "61030b30-3c25-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-61030b30-3c25-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "45e583f0-3c25-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-45e583f0-3c25-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "b76fbc30-3c1f-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-b76fbc30-3c1f-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "b479adb0-3c1f-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-b479adb0-3c1f-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692189295754, + 4294967370 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:34:55.754Z", + "version": "WzEwMywxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "[Flights] Delays & Cancellations #3", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"[Flights] Delays & Cancellations #3\",\"type\":\"metrics\",\"aggs\":[],\"params\":{\"annotations\":[{\"color\":\"rgba(0,98,177,1)\",\"fields\":\"FlightDelay,Cancelled,Carrier\",\"icon\":\"fa-exclamation-triangle\",\"id\":\"53b7dff0-4c89-11e8-a66a-6989ad5a0a39\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1,\"query_string\":{\"language\":\"lucene\",\"query\":\"FlightDelay:true AND Cancelled:true\"},\"template\":\"{{Carrier}}: Flight Delayed and Cancelled!\",\"time_field\":\"timestamp\",\"index_pattern_ref_name\":\"metrics_1_index_pattern\"}],\"axis_formatter\":\"number\",\"axis_max\":\"1\",\"axis_position\":\"left\",\"axis_scale\":\"normal\",\"drop_last_bucket\":0,\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"interval\":\">=1h\",\"isModelInvalid\":false,\"legend_position\":\"bottom\",\"max_lines_legend\":1,\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"rgba(0,156,224,1)\",\"fill\":0.5,\"formatter\":\"percent\",\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"label\":\"Percent Delays\",\"line_width\":\"2\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"numerator\":{\"language\":\"lucene\",\"query\":\"FlightDelay:true\"},\"type\":\"filter_ratio\",\"metric_agg\":\"min\",\"field\":\"FlightDelayMin\"}],\"point_size\":\"0\",\"separate_axis\":0,\"split_color_mode\":\"gradient\",\"split_mode\":\"everything\",\"stacked\":\"none\",\"time_range_mode\":\"entire_time_range\"}],\"show_grid\":1,\"show_legend\":0,\"time_field\":\"timestamp\",\"time_range_mode\":\"entire_time_range\",\"tooltip_mode\":\"show_all\",\"truncate_legend\":1,\"type\":\"timeseries\",\"use_kibana_indexes\":true,\"index_pattern_ref_name\":\"metrics_0_index_pattern\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:49:17.491Z", + "id": "4fcd3030-3c33-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "03402c40-3c33-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-03402c40-3c33-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "4ddb7250-3c33-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-4ddb7250-3c33-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "metrics_0_index_pattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "metrics_1_index_pattern", + "type": "index-pattern" + } + ], + "sort": [ + 1692190157491, + 4294967434 + ], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2023-08-16T12:49:17.491Z", + "version": "WzE1MCwxXQ==" +} + +{ + "attributes": { + "color": "#346d93", + "description": "", + "name": "find" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:40:27.763Z", + "id": "50864c30-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182427763, + 39 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:40:27.763Z", + "version": "Wzg4LDFd" +} + +{ + "attributes": { + "color": "#0e03aa", + "description": "", + "name": "stack" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:54:49.182Z", + "id": "51f867e0-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183289182, + 74 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:54:49.182Z", + "version": "WzE0NywxXQ==" +} + +{ + "attributes": { + "color": "#c93492", + "description": "", + "name": "store" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:40:31.656Z", + "id": "52d85280-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182431656, + 36 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:40:31.656Z", + "version": "Wzg5LDFd" +} + +{ + "attributes": { + "color": "#c9e3c5", + "description": "", + "name": "fog" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:42:17.587Z", + "id": "5584ec30-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692189737587, + 189 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:42:17.587Z", + "version": "Wzc0OSwxXQ==" +} + +{ + "attributes": { + "color": "#33894d", + "description": "", + "name": "update" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:40:36.547Z", + "id": "55c2a130-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182436547, + 37 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:40:36.547Z", + "version": "WzkwLDFd" +} + +{ + "attributes": { + "columns": [ + "Carrier", + "OriginCityName", + "OriginCountry", + "DestCityName", + "DestCountry", + "FlightTimeMin", + "AvgTicketPrice", + "Cancelled", + "FlightDelayType" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "timestamp", + "desc" + ] + ], + "title": "[Flights] Flight Log", + "version": 1 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:26:07.159Z", + "id": "571aaf70-4c88-11e8-b3d7-01146121b73d", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "sort": [ + 1692188767159, + 4294967298 + ], + "type": "search", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:26:07.159Z", + "version": "Wzc3LDFd" +} + +{ + "attributes": { + "color": "#26794a", + "description": "", + "name": "tags" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:54:58.547Z", + "id": "578d6430-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183298547, + 82 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:54:58.547Z", + "version": "WzE1MCwxXQ==" +} + +{ + "attributes": { + "color": "#9b6ba9", + "description": "", + "name": "migration" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T11:09:19.179Z", + "id": "588769b0-3c25-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692184159179, + 83 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T11:09:19.179Z", + "version": "WzE2NCwxXQ==" +} + +{ + "attributes": { + "color": "#ad4dd6", + "description": "", + "name": "snow" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:42:22.768Z", + "id": "589b7b00-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692189742768, + 190 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:42:22.768Z", + "version": "Wzc2NCwxXQ==" +} + +{ + "attributes": { + "color": "#fb27df", + "description": "", + "name": "sample data" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:40:45.165Z", + "id": "5ae5a1d0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182445165, + 32 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:40:45.165Z", + "version": "WzkxLDFd" +} + +{ + "attributes": { + "color": "#cfbc31", + "description": "", + "name": "role mappings" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:55:05.626Z", + "id": "5bc58fa0-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183305626, + 77 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:55:05.626Z", + "version": "WzE1MSwxXQ==" +} + +{ + "attributes": { + "color": "#c711ef", + "description": "", + "name": "rain" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:42:28.431Z", + "id": "5bfb95f0-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692189748431, + 191 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:42:28.431Z", + "version": "Wzc2NSwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "93d4f467-cd2a-438d-bf82-0d89d3594375": { + "columnOrder": [ + "db222e35-2792-4c1f-b8de-a4d8a2c022ee", + "720787a2-a250-4c41-a014-3bb8d3736454", + "db262b33-970d-40b5-9f59-d51d182d8849" + ], + "columns": { + "720787a2-a250-4c41-a014-3bb8d3736454": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "DestWeather", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "db262b33-970d-40b5-9f59-d51d182d8849", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "DestWeather" + }, + "db222e35-2792-4c1f-b8de-a4d8a2c022ee": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "OriginWeather", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "db262b33-970d-40b5-9f59-d51d182d8849", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "OriginWeather" + }, + "db262b33-970d-40b5-9f59-d51d182d8849": { + "dataType": "number", + "isBucketed": false, + "label": "Median of dayOfWeek", + "operationType": "median", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "dayOfWeek" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "layerId": "93d4f467-cd2a-438d-bf82-0d89d3594375", + "layerType": "data", + "legendDisplay": "default", + "metrics": [ + "db262b33-970d-40b5-9f59-d51d182d8849" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "db222e35-2792-4c1f-b8de-a4d8a2c022ee", + "720787a2-a250-4c41-a014-3bb8d3736454" + ] + } + ], + "shape": "donut" + } + }, + "title": "Weather", + "visualizationType": "lnsPie" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:42:31.117Z", + "id": "5d956fd0-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-93d4f467-cd2a-438d-bf82-0d89d3594375", + "type": "index-pattern" + }, + { + "id": "61030b30-3c25-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-61030b30-3c25-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "173d51b0-3c32-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-173d51b0-3c32-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "5584ec30-3c32-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-5584ec30-3c32-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "589b7b00-3c32-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-589b7b00-3c32-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "5bfb95f0-3c32-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-5bfb95f0-3c32-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692189751117, + 4294967392 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:42:31.117Z", + "version": "WzExNywxXQ==" +} + +{ + "attributes": { + "color": "#67ae9f", + "description": "", + "name": "actions" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T11:09:29.150Z", + "id": "5e78dde0-3c25-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692184169150, + 87 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T11:09:29.150Z", + "version": "WzE2NSwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "5861e7b7-9a07-4e4a-bb6e-6d8ac5fd8906": { + "columnOrder": [ + "248fe449-ee57-4e77-8fa3-7a4840ce73d2", + "c0b3784b-1a0e-478f-8d84-aeb65def20e8", + "ed8ddd99-72ba-434e-9542-922fe98df7e6" + ], + "columns": { + "248fe449-ee57-4e77-8fa3-7a4840ce73d2": { + "dataType": "string", + "isBucketed": true, + "label": "Top 4 values of Carrier", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "ed8ddd99-72ba-434e-9542-922fe98df7e6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 4 + }, + "scale": "ordinal", + "sourceField": "Carrier" + }, + "c0b3784b-1a0e-478f-8d84-aeb65def20e8": { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": { + "dropPartials": false, + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "timestamp" + }, + "ed8ddd99-72ba-434e-9542-922fe98df7e6": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "FlightNum", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "FlightNum" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "ed8ddd99-72ba-434e-9542-922fe98df7e6" + ], + "layerId": "5861e7b7-9a07-4e4a-bb6e-6d8ac5fd8906", + "layerType": "data", + "position": "top", + "seriesType": "line", + "showGridlines": false, + "splitAccessor": "248fe449-ee57-4e77-8fa3-7a4840ce73d2", + "xAccessor": "c0b3784b-1a0e-478f-8d84-aeb65def20e8" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "line", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "Flights by carrier #3", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:28:17.782Z", + "id": "60f4d960-3c30-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-5861e7b7-9a07-4e4a-bb6e-6d8ac5fd8906", + "type": "index-pattern" + } + ], + "sort": [ + 1692188897782, + 4294967353 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:28:17.782Z", + "version": "Wzg4LDFd" +} + +{ + "attributes": { + "color": "#c90e88", + "description": "", + "name": "watch" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:55:18.494Z", + "id": "63710fe0-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183318494, + 80 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:55:18.494Z", + "version": "WzE1MywxXQ==" +} + +{ + "attributes": { + "color": "#c3da8f", + "description": "", + "name": "bars" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:35:35.265Z", + "id": "65b77510-3c31-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692189335265, + 183 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:35:35.265Z", + "version": "WzY4NywxXQ==" +} + +{ + "attributes": { + "color": "#67d1cd", + "description": "", + "name": "upgrade" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:55:31.042Z", + "id": "6aebbc20-3c23-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692183331042, + 81 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:55:31.042Z", + "version": "WzE1NCwxXQ==" +} + +{ + "attributes": { + "color": "#2d236b", + "description": "", + "name": "buckets" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:42:55.436Z", + "id": "6c1438c0-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692189775436, + 194 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T12:42:55.436Z", + "version": "Wzc3MCwxXQ==" +} + +{ + "attributes": { + "color": "#a86609", + "description": "", + "name": "profile" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T11:10:01.320Z", + "id": "71a59e80-3c25-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692184201320, + 89 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T11:10:01.320Z", + "version": "WzE2OCwxXQ==" +} + +{ + "attributes": { + "color": "#d41137", + "description": "", + "name": "canvas" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:41:27.075Z", + "id": "73e07020-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182487075, + 38 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:41:27.075Z", + "version": "Wzk0LDFd" +} + +{ + "attributes": { + "color": "#f75098", + "description": "", + "name": "reporting" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:44:09.125Z", + "id": "d4777550-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182649125, + 48 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:44:09.125Z", + "version": "WzExMSwxXQ==" +} + +{ + "attributes": { + "color": "#a20855", + "description": "", + "name": "preview" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:43:12.851Z", + "id": "b2ecba30-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182592851, + 49 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:43:12.851Z", + "version": "WzEwNywxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "e52bf9e1-21bf-478e-ad85-2d43a775ba53": { + "columnOrder": [ + "188582f5-ab1c-437b-adaf-f9505f2c1b8a", + "9c9d8820-36b4-45d4-b0b0-ee548816ab03" + ], + "columns": { + "188582f5-ab1c-437b-adaf-f9505f2c1b8a": { + "dataType": "string", + "isBucketed": true, + "label": "Top 10 values of DestCountry", + "operationType": "terms", + "params": { + "accuracyMode": true, + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "9c9d8820-36b4-45d4-b0b0-ee548816ab03", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "DestCountry" + }, + "9c9d8820-36b4-45d4-b0b0-ee548816ab03": { + "dataType": "number", + "isBucketed": false, + "label": "Sum of DistanceMiles", + "operationType": "sum", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "DistanceMiles" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "9c9d8820-36b4-45d4-b0b0-ee548816ab03" + ], + "layerId": "e52bf9e1-21bf-478e-ad85-2d43a775ba53", + "layerType": "data", + "seriesType": "bar_stacked", + "xAccessor": "188582f5-ab1c-437b-adaf-f9505f2c1b8a" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "bar_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "Top Destanations - Bars", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:36:00.202Z", + "id": "74948aa0-3c31-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-e52bf9e1-21bf-478e-ad85-2d43a775ba53", + "type": "index-pattern" + }, + { + "id": "61030b30-3c25-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-61030b30-3c25-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "2dfb1430-3c25-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-2dfb1430-3c25-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "d4777550-3c21-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-d4777550-3c21-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "65b77510-3c31-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-65b77510-3c31-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "b2ecba30-3c21-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-b2ecba30-3c21-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692189360202, + 4294967378 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:36:00.202Z", + "version": "WzEwNSwxXQ==" +} + +{ + "attributes": { + "color": "#a51dc6", + "description": "", + "name": "maps" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:41:31.245Z", + "id": "765ce1d0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182491245, + 45 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:41:31.245Z", + "version": "Wzk1LDFd" +} + +{ + "attributes": { + "color": "#797447", + "description": "", + "name": "development" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T11:10:09.586Z", + "id": "7692e920-3c25-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692184209586, + 90 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T11:10:09.586Z", + "version": "WzE3MCwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "[Flights] Delays & Cancellations", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"[Flights] Delays & Cancellations\",\"type\":\"metrics\",\"aggs\":[],\"params\":{\"time_range_mode\":\"entire_time_range\",\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"rgba(0,156,224,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"filter_ratio\",\"numerator\":{\"query\":\"FlightDelay:true\",\"language\":\"lucene\"}}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"percent\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":\"0\",\"fill\":0.5,\"stacked\":\"none\",\"label\":\"Percent Delays\",\"split_color_mode\":\"gradient\"}],\"time_field\":\"timestamp\",\"interval\":\">=1h\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":0,\"show_grid\":1,\"annotations\":[{\"fields\":\"FlightDelay,Cancelled,Carrier\",\"template\":\"{{Carrier}}: Flight Delayed and Cancelled!\",\"query_string\":{\"query\":\"FlightDelay:true AND Cancelled:true\",\"language\":\"lucene\"},\"id\":\"53b7dff0-4c89-11e8-a66a-6989ad5a0a39\",\"color\":\"rgba(0,98,177,1)\",\"time_field\":\"timestamp\",\"icon\":\"fa-exclamation-triangle\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1,\"index_pattern_ref_name\":\"metrics_1_index_pattern\"}],\"legend_position\":\"bottom\",\"use_kibana_indexes\":true,\"axis_scale\":\"normal\",\"tooltip_mode\":\"show_all\",\"drop_last_bucket\":0,\"isModelInvalid\":false,\"axis_max\":\"1\",\"index_pattern_ref_name\":\"metrics_0_index_pattern\"}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:26:07.159Z", + "id": "bcb63b50-4c89-11e8-b3d7-01146121b73d", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "metrics_0_index_pattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "metrics_1_index_pattern", + "type": "index-pattern" + } + ], + "sort": [ + 1692188767159, + 4294967301 + ], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2023-08-16T12:26:07.159Z", + "version": "Wzc4LDFd" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":null,\"disabled\":false,\"key\":\"FlightDelayMin\",\"negate\":true,\"params\":{\"query\":0},\"type\":\"phrase\",\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match_phrase\":{\"FlightDelayMin\":{\"query\":0}}}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "[Flights] Delay Buckets", + "uiStateJSON": "{\"vis\":{\"legendOpen\":false}}", + "version": 1, + "visState": "{\"title\":\"[Flights] Delay Buckets\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{\"emptyAsNull\":false},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"histogram\",\"params\":{\"field\":\"FlightDelayMin\",\"autoExtendBounds\":false,\"interval\":30,\"used_interval\":30,\"min_doc_count\":false,\"has_extended_bounds\":false,\"extended_bounds\":{},\"customLabel\":\"Flight Delay Minutes\"},\"schema\":\"segment\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true,\"rotate\":0},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"detailedTooltip\":true,\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"isVislibVis\":true,\"radiusRatio\":0,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"legendSize\":\"auto\",\"truncateLegend\":true,\"maxLegendLines\":1}}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:26:07.159Z", + "id": "9886b410-4c8b-11e8-b3d7-01146121b73d", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + }, + { + "id": "6c1438c0-3c32-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-6c1438c0-3c32-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692189777008, + 4294967400 + ], + "type": "visualization", + "typeMigrationVersion": "8.5.0", + "updated_at": "2023-08-16T12:42:57.008Z", + "version": "WzEyMCwxXQ==" +} + +{ + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": "{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}", + "panelsJSON": "{\"85b632c8-3b7b-408d-8223-b0caccf75bd3\":{\"order\":0,\"width\":\"small\",\"grow\":true,\"type\":\"optionsListControl\",\"explicitInput\":{\"title\":\"Origin City\",\"fieldName\":\"OriginCityName\",\"id\":\"85b632c8-3b7b-408d-8223-b0caccf75bd3\",\"selectedOptions\":[],\"enhancements\":{}}},\"d4dc9d2b-5850-402a-921d-8a2cd0107156\":{\"order\":1,\"width\":\"small\",\"grow\":true,\"type\":\"optionsListControl\",\"explicitInput\":{\"title\":\"Destination City\",\"fieldName\":\"DestCityName\",\"id\":\"d4dc9d2b-5850-402a-921d-8a2cd0107156\",\"enhancements\":{}}},\"bee4a16a-f5c1-40b2-887e-db1b9ad9e15f\":{\"order\":2,\"width\":\"small\",\"grow\":true,\"type\":\"rangeSliderControl\",\"explicitInput\":{\"title\":\"Average Ticket Price\",\"fieldName\":\"AvgTicketPrice\",\"id\":\"bee4a16a-f5c1-40b2-887e-db1b9ad9e15f\",\"enhancements\":{}}}}" + }, + "description": "Analyze mock flight data for ES-Air, Logstash Airways, Kibana Airlines and JetBeats", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}" + }, + "optionsJSON": "{\"hidePanelTitles\":false,\"useMargins\":true}", + "panelsJSON": "[{\"version\":\"8.6.0\",\"type\":\"search\",\"gridData\":{\"x\":0,\"y\":47,\"w\":48,\"h\":15,\"i\":\"4\"},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"8.6.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":16,\"w\":24,\"h\":9,\"i\":\"7\"},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_7\"},{\"version\":\"8.6.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":36,\"w\":24,\"h\":11,\"i\":\"10\"},\"panelIndex\":\"10\",\"embeddableConfig\":{\"vis\":{\"colors\":{\"Count\":\"#1F78C1\"},\"legendOpen\":false},\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"8.6.0\",\"type\":\"visualization\",\"gridData\":{\"x\":36,\"y\":36,\"w\":12,\"h\":11,\"i\":\"21\"},\"panelIndex\":\"21\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_21\"},{\"version\":\"8.9.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":8,\"i\":\"6afc61f7-e2d5-45a3-9e7a-281160ad3eb9\"},\"panelIndex\":\"6afc61f7-e2d5-45a3-9e7a-281160ad3eb9\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"[Flights] Markdown Instructions\",\"description\":\"\",\"type\":\"markdown\",\"params\":{\"fontSize\":10,\"openLinksInNewTab\":true,\"markdown\":\"## Sample Flight data\\nThis dashboard contains sample data for you to play with. You can view it, search it, and interact with the visualizations. For more information about Kibana, check our [docs](https://www.elastic.co/guide/en/kibana/current/index.html).\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{}}},\"hidePanelTitles\":true,\"enhancements\":{},\"type\":\"visualization\"}},{\"version\":\"8.9.0\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":8,\"h\":8,\"i\":\"392b4936-f753-47bc-a98d-a4e41a0a4cd4\"},\"panelIndex\":\"392b4936-f753-47bc-a98d-a4e41a0a4cd4\",\"embeddableConfig\":{\"enhancements\":{},\"attributes\":{\"title\":\"[Flights] Total Flights\",\"description\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"8fa993db-c147-4954-adf7-4ff264d42576\":{\"columns\":{\"81124c45-6ab6-42f4-8859-495d55eb8065\":{\"label\":\"Total flights\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"customLabel\":true}},\"columnOrder\":[\"81124c45-6ab6-42f4-8859-495d55eb8065\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"layerId\":\"8fa993db-c147-4954-adf7-4ff264d42576\",\"accessor\":\"81124c45-6ab6-42f4-8859-495d55eb8065\",\"layerType\":\"data\",\"textAlign\":\"center\",\"titlePosition\":\"bottom\",\"size\":\"xl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-current-indexpattern\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-layer-8fa993db-c147-4954-adf7-4ff264d42576\",\"type\":\"index-pattern\"}]},\"hidePanelTitles\":true,\"type\":\"lens\"}},{\"version\":\"8.9.0\",\"type\":\"lens\",\"gridData\":{\"x\":32,\"y\":0,\"w\":8,\"h\":4,\"i\":\"9271deff-5a61-4665-83fc-f9fdc6bf0c0b\"},\"panelIndex\":\"9271deff-5a61-4665-83fc-f9fdc6bf0c0b\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsLegacyMetric\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"b4712d43-1e84-4f5b-878d-8e38ba748317\":{\"columns\":{\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0\":{\"label\":\"Part of count(kql='FlightDelay : true') / count()\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"FlightDelay : true\",\"language\":\"kuery\"},\"customLabel\":true},\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1\":{\"label\":\"Part of count(kql='FlightDelay : true') / count()\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"customLabel\":true},\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2\":{\"label\":\"Part of count(kql='FlightDelay : true') / count()\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1\"],\"location\":{\"min\":0,\"max\":41},\"text\":\"count(kql='FlightDelay : true') / count()\"}},\"references\":[\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1\"],\"customLabel\":true},\"7e8fe9b1-f45c-4f3d-9561-30febcd357ec\":{\"label\":\"Delayed\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"count(kql='FlightDelay : true') / count()\",\"isFormulaBroken\":false,\"format\":{\"id\":\"percent\",\"params\":{\"decimals\":1}}},\"references\":[\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2\"],\"customLabel\":true}},\"columnOrder\":[\"7e8fe9b1-f45c-4f3d-9561-30febcd357ec\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"layerId\":\"b4712d43-1e84-4f5b-878d-8e38ba748317\",\"accessor\":\"7e8fe9b1-f45c-4f3d-9561-30febcd357ec\",\"layerType\":\"data\",\"textAlign\":\"center\",\"titlePosition\":\"bottom\",\"size\":\"xl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-current-indexpattern\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317\",\"type\":\"index-pattern\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"8.9.0\",\"type\":\"lens\",\"gridData\":{\"x\":40,\"y\":0,\"w\":8,\"h\":4,\"i\":\"aa591c29-1a31-4ee1-a71d-b829c06fd162\"},\"panelIndex\":\"aa591c29-1a31-4ee1-a71d-b829c06fd162\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsLegacyMetric\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"b4712d43-1e84-4f5b-878d-8e38ba748317\":{\"columns\":{\"c7851241-5526-499a-960b-357af8c2ce5bX0\":{\"label\":\"Part of Delayed\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"customLabel\":true},\"c7851241-5526-499a-960b-357af8c2ce5bX1\":{\"label\":\"Part of Delayed\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"timeShift\":\"1w\",\"customLabel\":true},\"c7851241-5526-499a-960b-357af8c2ce5bX2\":{\"label\":\"Part of Delayed\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"subtract\",\"args\":[{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"c7851241-5526-499a-960b-357af8c2ce5bX0\",\"c7851241-5526-499a-960b-357af8c2ce5bX1\"],\"location\":{\"min\":0,\"max\":28},\"text\":\"count() / count(shift='1w') \"},1],\"location\":{\"min\":0,\"max\":31},\"text\":\"count() / count(shift='1w') - 1\"}},\"references\":[\"c7851241-5526-499a-960b-357af8c2ce5bX0\",\"c7851241-5526-499a-960b-357af8c2ce5bX1\"],\"customLabel\":true},\"c7851241-5526-499a-960b-357af8c2ce5b\":{\"label\":\"Delayed vs 1 week earlier\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"count() / count(shift='1w') - 1\",\"isFormulaBroken\":false,\"format\":{\"id\":\"percent\",\"params\":{\"decimals\":1}}},\"references\":[\"c7851241-5526-499a-960b-357af8c2ce5bX2\"],\"customLabel\":true}},\"columnOrder\":[\"c7851241-5526-499a-960b-357af8c2ce5b\",\"c7851241-5526-499a-960b-357af8c2ce5bX2\",\"c7851241-5526-499a-960b-357af8c2ce5bX0\",\"c7851241-5526-499a-960b-357af8c2ce5bX1\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"layerId\":\"b4712d43-1e84-4f5b-878d-8e38ba748317\",\"accessor\":\"c7851241-5526-499a-960b-357af8c2ce5b\",\"layerType\":\"data\",\"textAlign\":\"center\",\"titlePosition\":\"bottom\",\"size\":\"xl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"alias\":null,\"negate\":false,\"disabled\":false,\"type\":\"phrase\",\"key\":\"FlightDelay\",\"params\":{\"query\":true},\"index\":\"filter-index-pattern-0\"},\"query\":{\"match_phrase\":{\"FlightDelay\":true}},\"$state\":{\"store\":\"appState\"}}]},\"references\":[{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-current-indexpattern\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"filter-index-pattern-0\",\"type\":\"index-pattern\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"8.9.0\",\"type\":\"lens\",\"gridData\":{\"x\":32,\"y\":4,\"w\":8,\"h\":4,\"i\":\"b766e3b8-4544-46ed-99e6-9ecc4847e2a2\"},\"panelIndex\":\"b766e3b8-4544-46ed-99e6-9ecc4847e2a2\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsLegacyMetric\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"b4712d43-1e84-4f5b-878d-8e38ba748317\":{\"columns\":{\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0\":{\"label\":\"Part of Cancelled\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"Cancelled : true\",\"language\":\"kuery\"},\"customLabel\":true},\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1\":{\"label\":\"Part of Cancelled\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"customLabel\":true},\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2\":{\"label\":\"Part of Cancelled\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1\"],\"location\":{\"min\":0,\"max\":39},\"text\":\"count(kql='Cancelled : true') / count()\"}},\"references\":[\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1\"],\"customLabel\":true},\"7e8fe9b1-f45c-4f3d-9561-30febcd357ec\":{\"label\":\"Cancelled\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"count(kql='Cancelled : true') / count()\",\"isFormulaBroken\":false,\"format\":{\"id\":\"percent\",\"params\":{\"decimals\":1}}},\"references\":[\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2\"],\"customLabel\":true}},\"columnOrder\":[\"7e8fe9b1-f45c-4f3d-9561-30febcd357ec\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX0\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX1\",\"7e8fe9b1-f45c-4f3d-9561-30febcd357ecX2\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"layerId\":\"b4712d43-1e84-4f5b-878d-8e38ba748317\",\"accessor\":\"7e8fe9b1-f45c-4f3d-9561-30febcd357ec\",\"layerType\":\"data\",\"textAlign\":\"center\",\"titlePosition\":\"bottom\",\"size\":\"xl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-current-indexpattern\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317\",\"type\":\"index-pattern\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"8.9.0\",\"type\":\"lens\",\"gridData\":{\"x\":40,\"y\":4,\"w\":8,\"h\":4,\"i\":\"2e33ade5-96e5-40b4-b460-493e5d4fa834\"},\"panelIndex\":\"2e33ade5-96e5-40b4-b460-493e5d4fa834\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsLegacyMetric\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"b4712d43-1e84-4f5b-878d-8e38ba748317\":{\"columns\":{\"c7851241-5526-499a-960b-357af8c2ce5bX0\":{\"label\":\"Part of Delayed vs 1 week earlier\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"customLabel\":true},\"c7851241-5526-499a-960b-357af8c2ce5bX1\":{\"label\":\"Part of Delayed vs 1 week earlier\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"timeShift\":\"1w\",\"customLabel\":true},\"c7851241-5526-499a-960b-357af8c2ce5bX2\":{\"label\":\"Part of Delayed vs 1 week earlier\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"subtract\",\"args\":[{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"c7851241-5526-499a-960b-357af8c2ce5bX0\",\"c7851241-5526-499a-960b-357af8c2ce5bX1\"],\"location\":{\"min\":0,\"max\":28},\"text\":\"count() / count(shift='1w') \"},1],\"location\":{\"min\":0,\"max\":31},\"text\":\"count() / count(shift='1w') - 1\"}},\"references\":[\"c7851241-5526-499a-960b-357af8c2ce5bX0\",\"c7851241-5526-499a-960b-357af8c2ce5bX1\"],\"customLabel\":true},\"c7851241-5526-499a-960b-357af8c2ce5b\":{\"label\":\"Cancelled vs 1 week earlier\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"count() / count(shift='1w') - 1\",\"isFormulaBroken\":false,\"format\":{\"id\":\"percent\",\"params\":{\"decimals\":1}}},\"references\":[\"c7851241-5526-499a-960b-357af8c2ce5bX2\"],\"customLabel\":true}},\"columnOrder\":[\"c7851241-5526-499a-960b-357af8c2ce5b\",\"c7851241-5526-499a-960b-357af8c2ce5bX2\",\"c7851241-5526-499a-960b-357af8c2ce5bX0\",\"c7851241-5526-499a-960b-357af8c2ce5bX1\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"layerId\":\"b4712d43-1e84-4f5b-878d-8e38ba748317\",\"accessor\":\"c7851241-5526-499a-960b-357af8c2ce5b\",\"layerType\":\"data\",\"textAlign\":\"center\",\"titlePosition\":\"bottom\",\"size\":\"xl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"alias\":null,\"negate\":false,\"disabled\":false,\"type\":\"phrase\",\"key\":\"Cancelled\",\"params\":{\"query\":true},\"index\":\"filter-index-pattern-0\"},\"query\":{\"match_phrase\":{\"Cancelled\":true}},\"$state\":{\"store\":\"appState\"}}]},\"references\":[{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-current-indexpattern\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"filter-index-pattern-0\",\"type\":\"index-pattern\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"8.9.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":8,\"w\":24,\"h\":8,\"i\":\"086ac2e9-dd16-4b45-92b8-1e43ff7e3f65\"},\"panelIndex\":\"086ac2e9-dd16-4b45-92b8-1e43ff7e3f65\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"03c34665-471c-49c7-acf1-5a11f517421c\":{\"columns\":{\"a5b94e30-4e77-4b0a-9187-1d8b13de1456\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true}},\"3e267327-7317-4310-aee3-320e0f7c1e70\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\"}},\"columnOrder\":[\"a5b94e30-4e77-4b0a-9187-1d8b13de1456\",\"3e267327-7317-4310-aee3-320e0f7c1e70\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\",\"legendSize\":\"auto\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yLeftExtent\":{\"mode\":\"full\"},\"yRightExtent\":{\"mode\":\"custom\",\"lowerBound\":0,\"upperBound\":1},\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":false,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"03c34665-471c-49c7-acf1-5a11f517421c\",\"accessors\":[\"3e267327-7317-4310-aee3-320e0f7c1e70\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"a5b94e30-4e77-4b0a-9187-1d8b13de1456\",\"layerType\":\"data\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-current-indexpattern\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-layer-03c34665-471c-49c7-acf1-5a11f517421c\",\"type\":\"index-pattern\"}]},\"hidePanelTitles\":false,\"enhancements\":{},\"type\":\"lens\"},\"title\":\"[Flights] Flight count\"},{\"version\":\"8.9.0\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":8,\"w\":24,\"h\":28,\"i\":\"fb86b32f-fb7a-45cf-9511-f366fef51bbd\"},\"panelIndex\":\"fb86b32f-fb7a-45cf-9511-f366fef51bbd\",\"embeddableConfig\":{\"attributes\":{\"title\":\"Cities by delay, cancellation\",\"type\":\"lens\",\"visualizationType\":\"lnsDatatable\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"f26e8f7a-4118-4227-bea0-5c02d8b270f7\":{\"columns\":{\"3dd24cb4-45ef-4dd8-b22a-d7b802cb6da0\":{\"label\":\"Top values of OriginCityName\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"OriginCityName\",\"isBucketed\":true,\"params\":{\"size\":1000,\"orderBy\":{\"type\":\"alphabetical\",\"fallback\":true},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false}},\"52f6f2e9-6242-4c44-be63-b799150e7e60X0\":{\"label\":\"Part of Delay %\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"FlightDelay : true \",\"language\":\"kuery\"},\"customLabel\":true},\"52f6f2e9-6242-4c44-be63-b799150e7e60X1\":{\"label\":\"Part of Delay %\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"customLabel\":true},\"52f6f2e9-6242-4c44-be63-b799150e7e60X2\":{\"label\":\"Part of Delay %\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"52f6f2e9-6242-4c44-be63-b799150e7e60X0\",\"52f6f2e9-6242-4c44-be63-b799150e7e60X1\"],\"location\":{\"min\":0,\"max\":42},\"text\":\"count(kql='FlightDelay : true ') / count()\"}},\"references\":[\"52f6f2e9-6242-4c44-be63-b799150e7e60X0\",\"52f6f2e9-6242-4c44-be63-b799150e7e60X1\"],\"customLabel\":true},\"52f6f2e9-6242-4c44-be63-b799150e7e60\":{\"label\":\"Delay %\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"count(kql='FlightDelay : true ') / count()\",\"isFormulaBroken\":false,\"format\":{\"id\":\"percent\",\"params\":{\"decimals\":0}}},\"references\":[\"52f6f2e9-6242-4c44-be63-b799150e7e60X2\"],\"customLabel\":true},\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0\":{\"label\":\"Part of Cancel %\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"Cancelled: true\",\"language\":\"kuery\"},\"customLabel\":true},\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1\":{\"label\":\"Part of Cancel %\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"customLabel\":true},\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X2\":{\"label\":\"Part of Cancel %\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0\",\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1\"],\"location\":{\"min\":0,\"max\":38},\"text\":\"count(kql='Cancelled: true') / count()\"}},\"references\":[\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0\",\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1\"],\"customLabel\":true},\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6\":{\"label\":\"Cancel %\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"count(kql='Cancelled: true') / count()\",\"isFormulaBroken\":false,\"format\":{\"id\":\"percent\",\"params\":{\"decimals\":0}}},\"references\":[\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X2\"],\"customLabel\":true}},\"columnOrder\":[\"3dd24cb4-45ef-4dd8-b22a-d7b802cb6da0\",\"52f6f2e9-6242-4c44-be63-b799150e7e60\",\"52f6f2e9-6242-4c44-be63-b799150e7e60X0\",\"52f6f2e9-6242-4c44-be63-b799150e7e60X1\",\"52f6f2e9-6242-4c44-be63-b799150e7e60X2\",\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X0\",\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X1\",\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6X2\",\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"3dd24cb4-45ef-4dd8-b22a-d7b802cb6da0\",\"width\":262.75},{\"columnId\":\"52f6f2e9-6242-4c44-be63-b799150e7e60\",\"isTransposed\":false,\"width\":302.5,\"colorMode\":\"cell\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":5,\"stops\":[{\"color\":\"#f7e0b8\",\"stop\":0.6},{\"color\":\"#e7664c\",\"stop\":1}],\"name\":\"custom\",\"colorStops\":[{\"color\":\"#f7e0b8\",\"stop\":0.2},{\"color\":\"#e7664c\",\"stop\":0.6}],\"rangeType\":\"number\",\"rangeMin\":0.2,\"rangeMax\":0.6}},\"alignment\":\"center\"},{\"columnId\":\"7b9f3ece-9da3-4c27-b582-d3f8e8cc31d6\",\"isTransposed\":false,\"alignment\":\"center\",\"colorMode\":\"cell\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":5,\"stops\":[{\"color\":\"#f7e0b8\",\"stop\":0.6},{\"color\":\"#e7664c\",\"stop\":0.6666666666666666}],\"rangeType\":\"number\",\"name\":\"custom\",\"colorStops\":[{\"color\":\"#f7e0b8\",\"stop\":0.2},{\"color\":\"#e7664c\",\"stop\":0.6}],\"rangeMin\":0.2,\"rangeMax\":0.6}}}],\"layerId\":\"f26e8f7a-4118-4227-bea0-5c02d8b270f7\",\"sorting\":{\"columnId\":\"52f6f2e9-6242-4c44-be63-b799150e7e60\",\"direction\":\"desc\"},\"layerType\":\"data\",\"rowHeight\":\"single\",\"rowHeightLines\":1},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-current-indexpattern\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-layer-f26e8f7a-4118-4227-bea0-5c02d8b270f7\",\"type\":\"index-pattern\"}]},\"enhancements\":{},\"hidePanelTitles\":false,\"type\":\"lens\"},\"title\":\"[Flights] Most delayed cities\"},{\"version\":\"8.9.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":25,\"w\":24,\"h\":11,\"i\":\"0cc42484-16f7-42ec-b38c-9bf8be69cde7\"},\"panelIndex\":\"0cc42484-16f7-42ec-b38c-9bf8be69cde7\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"e80cc05e-c52a-4e5f-ac71-4b37274867f5\":{\"columns\":{\"caf7421e-93a3-439e-ab0a-fbdead93c21c\":{\"label\":\"Top values of FlightDelayType\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"FlightDelayType\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"column\",\"columnId\":\"0233d302-ec81-4fbe-96cb-7fac84cf035c\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"13ec79e3-9d73-4536-9056-3d92802bb30a\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true}},\"0233d302-ec81-4fbe-96cb-7fac84cf035c\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\"}},\"columnOrder\":[\"caf7421e-93a3-439e-ab0a-fbdead93c21c\",\"13ec79e3-9d73-4536-9056-3d92802bb30a\",\"0233d302-ec81-4fbe-96cb-7fac84cf035c\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\",\"legendSize\":\"auto\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yLeftExtent\":{\"mode\":\"full\"},\"yRightExtent\":{\"mode\":\"full\"},\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":false,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_percentage_stacked\",\"layers\":[{\"layerId\":\"e80cc05e-c52a-4e5f-ac71-4b37274867f5\",\"accessors\":[\"0233d302-ec81-4fbe-96cb-7fac84cf035c\"],\"position\":\"top\",\"seriesType\":\"bar_percentage_stacked\",\"showGridlines\":false,\"palette\":{\"type\":\"palette\",\"name\":\"cool\"},\"xAccessor\":\"13ec79e3-9d73-4536-9056-3d92802bb30a\",\"splitAccessor\":\"caf7421e-93a3-439e-ab0a-fbdead93c21c\",\"layerType\":\"data\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-current-indexpattern\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-layer-e80cc05e-c52a-4e5f-ac71-4b37274867f5\",\"type\":\"index-pattern\"}]},\"hidePanelTitles\":false,\"enhancements\":{},\"type\":\"lens\"},\"title\":\"[Flights] Delay Type\"},{\"version\":\"8.9.0\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":36,\"w\":12,\"h\":11,\"i\":\"5d53db36-2d5a-4adc-af7b-cec4c1a294e0\"},\"panelIndex\":\"5d53db36-2d5a-4adc-af7b-cec4c1a294e0\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"0c8e136b-a822-4fb3-836d-e06cbea4eea4\":{\"columns\":{\"d1cee8bf-34cf-4141-99d7-ff043ee77b56\":{\"label\":\"Top values of FlightDelayType\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"FlightDelayType\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"column\",\"columnId\":\"aa152ace-ee2d-447b-b86d-459bef4d7880\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"aa152ace-ee2d-447b-b86d-459bef4d7880\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\"}},\"columnOrder\":[\"d1cee8bf-34cf-4141-99d7-ff043ee77b56\",\"aa152ace-ee2d-447b-b86d-459bef4d7880\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"pie\",\"palette\":{\"type\":\"palette\",\"name\":\"cool\"},\"layers\":[{\"layerId\":\"0c8e136b-a822-4fb3-836d-e06cbea4eea4\",\"metrics\":[\"aa152ace-ee2d-447b-b86d-459bef4d7880\"],\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false,\"layerType\":\"data\",\"legendSize\":\"auto\",\"primaryGroups\":[\"d1cee8bf-34cf-4141-99d7-ff043ee77b56\"]}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"type\":\"phrase\",\"key\":\"FlightDelayType\",\"params\":{\"query\":\"No Delay\"},\"disabled\":false,\"negate\":true,\"alias\":null,\"index\":\"filter-index-pattern-0\"},\"query\":{\"match_phrase\":{\"FlightDelayType\":\"No Delay\"}},\"$state\":{\"store\":\"appState\"}}]},\"references\":[{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-current-indexpattern\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"indexpattern-datasource-layer-0c8e136b-a822-4fb3-836d-e06cbea4eea4\",\"type\":\"index-pattern\"},{\"id\":\"d3d7af60-4c81-11e8-b3d7-01146121b73d\",\"name\":\"filter-index-pattern-0\",\"type\":\"index-pattern\"}]},\"enhancements\":{},\"hidePanelTitles\":false,\"type\":\"lens\"},\"title\":\"[Flights] Delay Type\"}]", + "refreshInterval": { + "pause": true, + "value": 0 + }, + "timeFrom": "2022-10-19T09:00:00.000Z", + "timeRestore": true, + "timeTo": "2022-10-26T09:00:00.000Z", + "title": "[Flights] Global Flight Dashboard", + "version": 1 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:26:07.159Z", + "id": "7adfa750-4c81-11e8-b3d7-01146121b73d", + "managed": false, + "references": [ + { + "id": "571aaf70-4c88-11e8-b3d7-01146121b73d", + "name": "4:panel_4", + "type": "search" + }, + { + "id": "bcb63b50-4c89-11e8-b3d7-01146121b73d", + "name": "7:panel_7", + "type": "visualization" + }, + { + "id": "9886b410-4c8b-11e8-b3d7-01146121b73d", + "name": "10:panel_10", + "type": "visualization" + }, + { + "id": "293b5a30-4c8f-11e8-b3d7-01146121b73d", + "name": "21:panel_21", + "type": "visualization" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "392b4936-f753-47bc-a98d-a4e41a0a4cd4:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "392b4936-f753-47bc-a98d-a4e41a0a4cd4:indexpattern-datasource-layer-8fa993db-c147-4954-adf7-4ff264d42576", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "9271deff-5a61-4665-83fc-f9fdc6bf0c0b:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "9271deff-5a61-4665-83fc-f9fdc6bf0c0b:indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "aa591c29-1a31-4ee1-a71d-b829c06fd162:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "aa591c29-1a31-4ee1-a71d-b829c06fd162:indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "aa591c29-1a31-4ee1-a71d-b829c06fd162:filter-index-pattern-0", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "b766e3b8-4544-46ed-99e6-9ecc4847e2a2:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "b766e3b8-4544-46ed-99e6-9ecc4847e2a2:indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "2e33ade5-96e5-40b4-b460-493e5d4fa834:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "2e33ade5-96e5-40b4-b460-493e5d4fa834:indexpattern-datasource-layer-b4712d43-1e84-4f5b-878d-8e38ba748317", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "2e33ade5-96e5-40b4-b460-493e5d4fa834:filter-index-pattern-0", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "086ac2e9-dd16-4b45-92b8-1e43ff7e3f65:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "086ac2e9-dd16-4b45-92b8-1e43ff7e3f65:indexpattern-datasource-layer-03c34665-471c-49c7-acf1-5a11f517421c", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "fb86b32f-fb7a-45cf-9511-f366fef51bbd:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "fb86b32f-fb7a-45cf-9511-f366fef51bbd:indexpattern-datasource-layer-f26e8f7a-4118-4227-bea0-5c02d8b270f7", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "0cc42484-16f7-42ec-b38c-9bf8be69cde7:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "0cc42484-16f7-42ec-b38c-9bf8be69cde7:indexpattern-datasource-layer-e80cc05e-c52a-4e5f-ac71-4b37274867f5", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "5d53db36-2d5a-4adc-af7b-cec4c1a294e0:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "5d53db36-2d5a-4adc-af7b-cec4c1a294e0:indexpattern-datasource-layer-0c8e136b-a822-4fb3-836d-e06cbea4eea4", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "5d53db36-2d5a-4adc-af7b-cec4c1a294e0:filter-index-pattern-0", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "controlGroup_85b632c8-3b7b-408d-8223-b0caccf75bd3:optionsListDataView", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "controlGroup_d4dc9d2b-5850-402a-921d-8a2cd0107156:optionsListDataView", + "type": "index-pattern" + }, + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "controlGroup_bee4a16a-f5c1-40b2-887e-db1b9ad9e15f:rangeSliderDataView", + "type": "index-pattern" + } + ], + "sort": [ + 1692188767159, + 4294967335 + ], + "type": "dashboard", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:26:07.159Z", + "version": "WzgxLDFd" +} + +{ + "attributes": { + "color": "#f762d0", + "description": "", + "name": "stack management" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:41:39.039Z", + "id": "7b0226f0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182499039, + 40 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:41:39.039Z", + "version": "Wzk2LDFd" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "cb26e91d-0305-436c-96db-b5910b808f6e": { + "columnOrder": [ + "3c4357a4-b3b2-43f2-8bf3-ec96d16f77fe", + "721050d3-0af2-4333-8866-2f33d6680cfa", + "7ef5d4a6-c5aa-426d-b46d-722a33f1da52", + "580e2cb4-4f4c-4a43-894e-303c1473e650" + ], + "columns": { + "3c4357a4-b3b2-43f2-8bf3-ec96d16f77fe": { + "dataType": "string", + "isBucketed": true, + "label": "Top 3 values of DestCityName", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "7ef5d4a6-c5aa-426d-b46d-722a33f1da52", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "DestCityName" + }, + "580e2cb4-4f4c-4a43-894e-303c1473e650": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "DistanceKilometers", + "operationType": "median", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "DistanceKilometers" + }, + "721050d3-0af2-4333-8866-2f33d6680cfa": { + "dataType": "string", + "isBucketed": true, + "label": "Top 10 values of DestAirportID", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "7ef5d4a6-c5aa-426d-b46d-722a33f1da52", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "DestAirportID" + }, + "7ef5d4a6-c5aa-426d-b46d-722a33f1da52": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "7ef5d4a6-c5aa-426d-b46d-722a33f1da52", + "580e2cb4-4f4c-4a43-894e-303c1473e650" + ], + "layerId": "cb26e91d-0305-436c-96db-b5910b808f6e", + "layerType": "data", + "position": "top", + "seriesType": "bar_stacked", + "showGridlines": false, + "splitAccessor": "721050d3-0af2-4333-8866-2f33d6680cfa", + "xAccessor": "3c4357a4-b3b2-43f2-8bf3-ec96d16f77fe" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "bar_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "Destination & Distance #2", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:43:29.920Z", + "id": "80a21000-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-cb26e91d-0305-436c-96db-b5910b808f6e", + "type": "index-pattern" + }, + { + "id": "2d7bbcf0-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-2d7bbcf0-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "65b77510-3c31-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-65b77510-3c31-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692189809920, + 4294967396 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:43:29.920Z", + "version": "WzEyMiwxXQ==" +} + +{ + "attributes": { + "color": "#aa4016", + "description": "", + "name": "policy" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:41:54.835Z", + "id": "846c6e30-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182514835, + 42 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:41:54.835Z", + "version": "Wzk3LDFd" +} + +{ + "attributes": { + "color": "#aa830b", + "description": "", + "name": "connection" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:42:01.843Z", + "id": "8899c430-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182521843, + 41 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:42:01.843Z", + "version": "Wzk4LDFd" +} + +{ + "attributes": { + "color": "#dd104d", + "description": "", + "name": "users" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:44:20.909Z", + "id": "db7d8dd0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182660909, + 57 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:44:20.909Z", + "version": "WzExNSwxXQ==" +} + +{ + "attributes": { + "color": "#7aeaaa", + "description": "", + "name": "flights" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:28:21.512Z", + "id": "9fa53080-3c1f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181701512, + 10 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:28:21.512Z", + "version": "WzI1LDFd" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "d6d1708e-505b-47b4-b23e-cd883a872588": { + "columnOrder": [ + "da5e742a-a097-487c-b27b-e12aa926a113", + "781363fb-a33e-47db-be26-d20d24cc7635", + "c3db66cd-10a4-4956-8add-abb0c520105c" + ], + "columns": { + "781363fb-a33e-47db-be26-d20d24cc7635": { + "dataType": "number", + "isBucketed": false, + "label": "Median of FlightTimeMin", + "operationType": "median", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "FlightTimeMin" + }, + "c3db66cd-10a4-4956-8add-abb0c520105c": { + "dataType": "number", + "isBucketed": false, + "label": "Median of DistanceMiles", + "operationType": "median", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "DistanceMiles" + }, + "da5e742a-a097-487c-b27b-e12aa926a113": { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": { + "dropPartials": false, + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "timestamp" + } + }, + "incompleteColumns": {} + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "781363fb-a33e-47db-be26-d20d24cc7635", + "c3db66cd-10a4-4956-8add-abb0c520105c" + ], + "layerId": "d6d1708e-505b-47b4-b23e-cd883a872588", + "layerType": "data", + "seriesType": "bar_horizontal", + "xAccessor": "da5e742a-a097-487c-b27b-e12aa926a113" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "bar_horizontal", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "Flights Time and Miles", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:51:26.949Z", + "id": "9cf6e950-3c33-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-d6d1708e-505b-47b4-b23e-cd883a872588", + "type": "index-pattern" + }, + { + "id": "db7d8dd0-3c21-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-db7d8dd0-3c21-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "9fa53080-3c1f-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-9fa53080-3c1f-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692190286949, + 4294967438 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:51:26.949Z", + "version": "WzE1NiwxXQ==" +} + +{ + "attributes": { + "color": "#6cf890", + "description": "", + "name": "observability" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:35:28.427Z", + "id": "9e1b3fb0-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182128427, + 25 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:35:28.427Z", + "version": "WzcyLDFd" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "3be92f0c-b6e0-4bb1-b68f-51b8a9924b2a": { + "columnOrder": [ + "4d394c6e-f469-4e14-8913-311ba8ed72e4", + "a77fab82-4ef6-42c1-8959-29f35b1ee7bd", + "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f" + ], + "columns": { + "4d394c6e-f469-4e14-8913-311ba8ed72e4": { + "dataType": "string", + "isBucketed": true, + "label": "Top 10 values of FlightNum", + "operationType": "terms", + "params": { + "accuracyMode": true, + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "FlightNum" + }, + "a77fab82-4ef6-42c1-8959-29f35b1ee7bd": { + "dataType": "string", + "isBucketed": true, + "label": "Top 3 values of Origin", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "Origin" + }, + "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f": { + "dataType": "number", + "isBucketed": false, + "label": "Unique count of FlightDelayType", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "FlightDelayType" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "gridConfig": { + "isCellLabelVisible": false, + "isXAxisLabelVisible": true, + "isXAxisTitleVisible": false, + "isYAxisLabelVisible": true, + "isYAxisTitleVisible": false, + "type": "heatmap_grid" + }, + "layerId": "3be92f0c-b6e0-4bb1-b68f-51b8a9924b2a", + "layerType": "data", + "legend": { + "isVisible": true, + "position": "right", + "type": "heatmap_legend" + }, + "shape": "heatmap", + "valueAccessor": "bb8f978d-d70b-4d70-8d9e-f2cd49ac286f", + "xAccessor": "4d394c6e-f469-4e14-8913-311ba8ed72e4", + "yAccessor": "a77fab82-4ef6-42c1-8959-29f35b1ee7bd" + } + }, + "title": "Delays #3", + "visualizationType": "lnsHeatmap" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:44:27.586Z", + "id": "a3013220-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-3be92f0c-b6e0-4bb1-b68f-51b8a9924b2a", + "type": "index-pattern" + }, + { + "id": "61030b30-3c25-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-61030b30-3c25-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "b76fbc30-3c1f-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-b76fbc30-3c1f-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-5e9837a0-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "b479adb0-3c1f-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-b479adb0-3c1f-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "73e07020-3c21-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-73e07020-3c21-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692189867586, + 4294967407 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:44:27.586Z", + "version": "WzEyNCwxXQ==" +} + +{ + "attributes": { + "color": "#c51883", + "description": "", + "name": "events" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:35:44.641Z", + "id": "a7c54f10-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182144641, + 27 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:35:44.641Z", + "version": "Wzc0LDFd" +} + +{ + "attributes": { + "color": "#e5f434", + "description": "", + "name": "image" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:42:54.315Z", + "id": "a7e05bb0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182574315, + 43 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:42:54.315Z", + "version": "WzEwMiwxXQ==" +} + +{ + "attributes": { + "color": "#87029b", + "description": "", + "name": "traffic" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:28:37.836Z", + "id": "a96008c0-3c1f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181717836, + 11 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:28:37.836Z", + "version": "WzI2LDFd" +} + +{ + "attributes": { + "color": "#f042b0", + "description": "", + "name": "media" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:42:57.877Z", + "id": "a9ffe050-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182577877, + 44 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:42:57.877Z", + "version": "WzEwMywxXQ==" +} + +{ + "attributes": { + "color": "#68332b", + "description": "", + "name": "web" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:28:43.530Z", + "id": "acc4dea0-3c1f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181723530, + 13 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:28:43.530Z", + "version": "WzI3LDFd" +} + +{ + "attributes": { + "color": "#20ccba", + "description": "", + "name": "doc" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:43:02.766Z", + "id": "ace9e0e0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182582766, + 46 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:43:02.766Z", + "version": "WzEwNCwxXQ==" +} + +{ + "attributes": { + "color": "#483808", + "description": "", + "name": "docs" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:43:06.537Z", + "id": "af294990-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182586537, + 53 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:43:06.537Z", + "version": "WzEwNSwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "5861e7b7-9a07-4e4a-bb6e-6d8ac5fd8906": { + "columnOrder": [ + "248fe449-ee57-4e77-8fa3-7a4840ce73d2", + "c0b3784b-1a0e-478f-8d84-aeb65def20e8", + "ed8ddd99-72ba-434e-9542-922fe98df7e6" + ], + "columns": { + "248fe449-ee57-4e77-8fa3-7a4840ce73d2": { + "dataType": "string", + "isBucketed": true, + "label": "Top 4 values of Carrier", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "ed8ddd99-72ba-434e-9542-922fe98df7e6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 4 + }, + "scale": "ordinal", + "sourceField": "Carrier" + }, + "c0b3784b-1a0e-478f-8d84-aeb65def20e8": { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": { + "dropPartials": false, + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "timestamp" + }, + "ed8ddd99-72ba-434e-9542-922fe98df7e6": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "FlightNum", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "FlightNum" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "ed8ddd99-72ba-434e-9542-922fe98df7e6" + ], + "layerId": "5861e7b7-9a07-4e4a-bb6e-6d8ac5fd8906", + "layerType": "data", + "position": "top", + "seriesType": "bar_stacked", + "showGridlines": false, + "splitAccessor": "248fe449-ee57-4e77-8fa3-7a4840ce73d2", + "xAccessor": "c0b3784b-1a0e-478f-8d84-aeb65def20e8" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "bar_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "Flights by carrier", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:23:24.890Z", + "id": "b26113a0-3c2f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-5861e7b7-9a07-4e4a-bb6e-6d8ac5fd8906", + "type": "index-pattern" + } + ], + "sort": [ + 1692188604890, + 4294967342 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:23:24.890Z", + "version": "WzcwLDFd" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "d6d1708e-505b-47b4-b23e-cd883a872588": { + "columnOrder": [ + "da5e742a-a097-487c-b27b-e12aa926a113", + "781363fb-a33e-47db-be26-d20d24cc7635", + "c3db66cd-10a4-4956-8add-abb0c520105c" + ], + "columns": { + "781363fb-a33e-47db-be26-d20d24cc7635": { + "dataType": "number", + "isBucketed": false, + "label": "Median of FlightTimeMin", + "operationType": "median", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "FlightTimeMin" + }, + "c3db66cd-10a4-4956-8add-abb0c520105c": { + "dataType": "number", + "isBucketed": false, + "label": "Median of DistanceMiles", + "operationType": "median", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "DistanceMiles" + }, + "da5e742a-a097-487c-b27b-e12aa926a113": { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": { + "dropPartials": false, + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "timestamp" + } + }, + "incompleteColumns": {} + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "781363fb-a33e-47db-be26-d20d24cc7635", + "c3db66cd-10a4-4956-8add-abb0c520105c" + ], + "layerId": "d6d1708e-505b-47b4-b23e-cd883a872588", + "layerType": "data", + "seriesType": "bar_stacked", + "xAccessor": "da5e742a-a097-487c-b27b-e12aa926a113" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "bar_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "Flights Time and Miles #2", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:52:03.695Z", + "id": "b2dde7f0-3c33-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-d6d1708e-505b-47b4-b23e-cd883a872588", + "type": "index-pattern" + }, + { + "id": "1ce38c10-3c32-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-1ce38c10-3c32-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "9fa53080-3c1f-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-9fa53080-3c1f-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "40357070-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-40357070-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692190323695, + 4294967443 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:52:03.695Z", + "version": "WzE1OSwxXQ==" +} + +{ + "attributes": { + "color": "#80b199", + "description": "", + "name": "payload" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:43:17.604Z", + "id": "b5c1fa40-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182597604, + 50 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:43:17.604Z", + "version": "WzEwOCwxXQ==" +} + +{ + "attributes": { + "color": "#a523ef", + "description": "", + "name": "content" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:43:33.073Z", + "id": "befa5c10-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182613073, + 51 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:43:33.073Z", + "version": "WzEwOSwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "5861e7b7-9a07-4e4a-bb6e-6d8ac5fd8906": { + "columnOrder": [ + "248fe449-ee57-4e77-8fa3-7a4840ce73d2", + "c0b3784b-1a0e-478f-8d84-aeb65def20e8", + "ed8ddd99-72ba-434e-9542-922fe98df7e6" + ], + "columns": { + "248fe449-ee57-4e77-8fa3-7a4840ce73d2": { + "dataType": "string", + "isBucketed": true, + "label": "Top 4 values of Carrier", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "ed8ddd99-72ba-434e-9542-922fe98df7e6", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 4 + }, + "scale": "ordinal", + "sourceField": "Carrier" + }, + "c0b3784b-1a0e-478f-8d84-aeb65def20e8": { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": { + "dropPartials": false, + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "timestamp" + }, + "ed8ddd99-72ba-434e-9542-922fe98df7e6": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "FlightNum", + "operationType": "unique_count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "FlightNum" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "ed8ddd99-72ba-434e-9542-922fe98df7e6" + ], + "layerId": "5861e7b7-9a07-4e4a-bb6e-6d8ac5fd8906", + "layerType": "data", + "position": "top", + "seriesType": "bar_percentage_stacked", + "showGridlines": false, + "splitAccessor": "248fe449-ee57-4e77-8fa3-7a4840ce73d2", + "xAccessor": "c0b3784b-1a0e-478f-8d84-aeb65def20e8" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "bar_percentage_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "Flights by carrier #2", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:23:46.362Z", + "id": "bf2d71a0-3c2f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-5861e7b7-9a07-4e4a-bb6e-6d8ac5fd8906", + "type": "index-pattern" + } + ], + "sort": [ + 1692188626362, + 4294967340 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:23:46.362Z", + "version": "WzcyLDFd" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "e52bf9e1-21bf-478e-ad85-2d43a775ba53": { + "columnOrder": [ + "188582f5-ab1c-437b-adaf-f9505f2c1b8a", + "9c9d8820-36b4-45d4-b0b0-ee548816ab03" + ], + "columns": { + "188582f5-ab1c-437b-adaf-f9505f2c1b8a": { + "dataType": "string", + "isBucketed": true, + "label": "Top 10 values of DestCountry", + "operationType": "terms", + "params": { + "accuracyMode": true, + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "9c9d8820-36b4-45d4-b0b0-ee548816ab03", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "DestCountry" + }, + "9c9d8820-36b4-45d4-b0b0-ee548816ab03": { + "dataType": "number", + "isBucketed": false, + "label": "Sum of DistanceMiles", + "operationType": "sum", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "DistanceMiles" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "layerId": "e52bf9e1-21bf-478e-ad85-2d43a775ba53", + "layerType": "data", + "legendDisplay": "default", + "metrics": [ + "9c9d8820-36b4-45d4-b0b0-ee548816ab03" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "188582f5-ab1c-437b-adaf-f9505f2c1b8a" + ] + } + ], + "shape": "donut" + } + }, + "title": "Top Destinations -Donut", + "visualizationType": "lnsPie" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:45:21.908Z", + "id": "c3621340-3c32-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-e52bf9e1-21bf-478e-ad85-2d43a775ba53", + "type": "index-pattern" + }, + { + "id": "51f867e0-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-51f867e0-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "40357070-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-40357070-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + }, + { + "id": "21e1eb80-3c23-11ee-8bc8-574823b6bb7b", + "name": "tag-ref-21e1eb80-3c23-11ee-8bc8-574823b6bb7b", + "type": "tag" + } + ], + "sort": [ + 1692189921908, + 4294967412 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:45:21.908Z", + "version": "WzEyNywxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "cb26e91d-0305-436c-96db-b5910b808f6e": { + "columnOrder": [ + "721050d3-0af2-4333-8866-2f33d6680cfa", + "3c4357a4-b3b2-43f2-8bf3-ec96d16f77fe", + "7ef5d4a6-c5aa-426d-b46d-722a33f1da52", + "580e2cb4-4f4c-4a43-894e-303c1473e650" + ], + "columns": { + "3c4357a4-b3b2-43f2-8bf3-ec96d16f77fe": { + "dataType": "string", + "isBucketed": true, + "label": "Top 3 values of DestCityName", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "7ef5d4a6-c5aa-426d-b46d-722a33f1da52", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "DestCityName" + }, + "580e2cb4-4f4c-4a43-894e-303c1473e650": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "DistanceKilometers", + "operationType": "median", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "DistanceKilometers" + }, + "721050d3-0af2-4333-8866-2f33d6680cfa": { + "dataType": "string", + "isBucketed": true, + "label": "Top 10 values of DestAirportID", + "operationType": "terms", + "params": { + "exclude":[], + "excludeIsRegex": false, + "include":[], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "7ef5d4a6-c5aa-426d-b46d-722a33f1da52", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "DestAirportID" + }, + "7ef5d4a6-c5aa-426d-b46d-722a33f1da52": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": true + }, + "scale": "ratio", + "sourceField": "___records___" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "7ef5d4a6-c5aa-426d-b46d-722a33f1da52", + "580e2cb4-4f4c-4a43-894e-303c1473e650" + ], + "layerId": "cb26e91d-0305-436c-96db-b5910b808f6e", + "layerType": "data", + "position": "top", + "seriesType": "bar_stacked", + "showGridlines": false, + "splitAccessor": "3c4357a4-b3b2-43f2-8bf3-ec96d16f77fe", + "xAccessor": "721050d3-0af2-4333-8866-2f33d6680cfa" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "bar_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "Destination & Distance", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T12:31:13.732Z", + "id": "c9d4b040-3c30-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [ + { + "id": "d3d7af60-4c81-11e8-b3d7-01146121b73d", + "name": "indexpattern-datasource-layer-cb26e91d-0305-436c-96db-b5910b808f6e", + "type": "index-pattern" + } + ], + "sort": [ + 1692189073732, + 4294967351 + ], + "type": "lens", + "typeMigrationVersion": "8.9.0", + "updated_at": "2023-08-16T12:31:13.732Z", + "version": "WzkzLDFd" +} + +{ + "attributes": { + "color": "#5e7c98", + "description": "", + "name": "machine learning" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:44:02.199Z", + "id": "d056a270-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182642199, + 47 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:44:02.199Z", + "version": "WzExMCwxXQ==" +} + +{ + "attributes": { + "color": "#3ce2ee", + "description": "", + "name": "elastic" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:29:44.128Z", + "id": "d0e36400-3c1f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181784128, + 16 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:29:44.128Z", + "version": "WzQ0LDFd" +} + +{ + "attributes": { + "color": "#80b563", + "description": "", + "name": "kbn" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:37:03.700Z", + "id": "d6e49a30-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182223700, + 29 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:37:03.700Z", + "version": "Wzc3LDFd" +} + +{ + "attributes": { + "color": "#6f0dc1", + "description": "", + "name": "mock" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:29:59.255Z", + "id": "d9e79670-3c1f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181799255, + 18 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:29:59.255Z", + "version": "WzQ4LDFd" +} + +{ + "attributes": { + "color": "#f26e00", + "description": "", + "name": "test" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:37:08.995Z", + "id": "da0cb530-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182228995, + 30 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:37:08.995Z", + "version": "Wzc4LDFd" +} + +{ + "attributes": { + "color": "#bd0dbd", + "description": "", + "name": "prod" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:37:13.464Z", + "id": "dcb69f80-3c20-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182233464, + 31 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:37:13.464Z", + "version": "Wzc5LDFd" +} + +{ + "attributes": { + "color": "#b90b18", + "description": "", + "name": "roles" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:44:24.532Z", + "id": "dda66140-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182664532, + 58 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:44:24.532Z", + "version": "WzExOCwxXQ==" +} + +{ + "attributes": { + "color": "#72c184", + "description": "", + "name": "ci" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:44:29.509Z", + "id": "e09dcf50-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182669509, + 60 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:44:29.509Z", + "version": "WzExOSwxXQ==" +} + +{ + "attributes": { + "color": "#d6e046", + "description": "", + "name": "transforms" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:44:36.205Z", + "id": "e49b89d0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182676205, + 54 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:44:36.205Z", + "version": "WzEyMCwxXQ==" +} + +{ + "attributes": { + "color": "#583df4", + "description": "", + "name": "migration" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:44:58.128Z", + "id": "f1acb900-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182698128, + 55 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:44:58.128Z", + "version": "WzEyMSwxXQ==" +} + +{ + "attributes": { + "color": "#108c83", + "description": "", + "name": "cluster" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:45:04.002Z", + "id": "f52d0620-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182704002, + 59 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:45:04.002Z", + "version": "WzEyMiwxXQ==" +} + +{ + "attributes": { + "color": "#96c4c2", + "description": "", + "name": "logstash" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:45:14.430Z", + "id": "fb6435e0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182714430, + 56 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:45:14.430Z", + "version": "WzEyMywxXQ==" +} + +{ + "attributes": { + "color": "#54bd93", + "description": "", + "name": "trips" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:30:56.133Z", + "id": "fbce7b50-3c1f-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692181856133, + 22 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:30:56.133Z", + "version": "WzU4LDFd" +} + +{ + "attributes": { + "color": "#043eea", + "description": "", + "name": "ingest" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-16T10:45:19.900Z", + "id": "fea6ddc0-3c21-11ee-8bc8-574823b6bb7b", + "managed": false, + "references": [], + "sort": [ + 1692182719900, + 63 + ], + "type": "tag", + "typeMigrationVersion": "8.0.0", + "updated_at": "2023-08-16T10:45:19.900Z", + "version": "WzEyNCwxXQ==" +} + +{ + "attributes":{ + "color":"#a13120", + "description":"", + "name":"carrier" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:48:50.899Z", + "id":"14045230-4021-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:48:50.899Z", + "version":"WzEyMzUsMV0=" +} + +{ + "attributes":{ + "color":"#881325", + "description":"visualizations", + "name":"viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:46:30.299Z", + "id":"c0364fa0-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:46:30.299Z", + "version":"WzEyMDQsMV0=" +} + +{ + "attributes":{ + "color":"#d5732c", + "description":"viz", + "name":"viz data" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:46:16.518Z", + "id":"b7ffa660-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:46:16.518Z", + "version":"WzEyMDMsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"pie", + "name":"pie viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:43.551Z", + "id":"a45948f0-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:43.551Z", + "version":"WzEyMDIsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"pie", + "name":"pie viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:41.565Z", + "id":"a32a3ed0-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:41.565Z", + "version":"WzEyMDEsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"pie", + "name":"pie viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:39.597Z", + "id":"a1fdf3d0-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:39.597Z", + "version":"WzEyMDAsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"pie", + "name":"pie viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:37.420Z", + "id":"a0b1c4c0-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:37.420Z", + "version":"WzExOTksMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"pie", + "name":"pie viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:35.496Z", + "id":"9f8c3080-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:35.496Z", + "version":"WzExOTgsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"pie", + "name":"pie viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:32.861Z", + "id":"9dfa1ed0-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:32.861Z", + "version":"WzExOTcsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"donut", + "name":"donut viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:07.352Z", + "id":"8ec5c180-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:07.352Z", + "version":"WzExOTYsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"donut", + "name":"donut viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:05.396Z", + "id":"8d9b4b40-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:05.396Z", + "version":"WzExOTUsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"donut", + "name":"donut viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:03.256Z", + "id":"8c54c180-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:03.256Z", + "version":"WzExOTQsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"donut", + "name":"donut viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:45:00.628Z", + "id":"8ac3c140-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:45:00.628Z", + "version":"WzExOTMsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"donut", + "name":"donut viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:44:58.184Z", + "id":"894ed480-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:44:58.184Z", + "version":"WzExOTIsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"donut", + "name":"donut viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:44:56.044Z", + "id":"88084ac0-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:44:56.044Z", + "version":"WzExOTEsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"donut", + "name":"donut viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:44:54.109Z", + "id":"86e108d0-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:44:54.109Z", + "version":"WzExOTAsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"donut", + "name":"donut viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:44:52.448Z", + "id":"85e39600-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:44:52.448Z", + "version":"WzExODksMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"donut", + "name":"donut viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:44:49.629Z", + "id":"843570d0-4020-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:44:49.629Z", + "version":"WzExODgsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"xy", + "name":"xy viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:23:34.535Z", + "id":"8c318970-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:23:34.535Z", + "version":"WzExNzksMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"xy", + "name":"xy viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:23:32.348Z", + "id":"8ae3d3c0-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:23:32.348Z", + "version":"WzExNzgsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"xy", + "name":"xy viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:23:30.318Z", + "id":"89ae12e0-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:23:30.318Z", + "version":"WzExNzcsMV0=" +} + +{ + "attributes":{ + "color":"#64be14", + "description":"OMDswjeovAMPQDwm9406ljODd6ljhvrm4YwUnjdyHrT8XPls7qGseQEVnbbRDTqxc1tJpnRbNZzLXImPEuJuc43qCNaj2tTz3ryf", + "name":"long string" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:23:03.635Z", + "id":"79c69230-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:23:03.635Z", + "version":"WzExNzYsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"bar", + "name":"bar viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:21:53.111Z", + "id":"4fbd7670-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:21:53.111Z", + "version":"WzExNjYsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"bar", + "name":"bar viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:21:50.890Z", + "id":"4e6a90a0-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:21:50.890Z", + "version":"WzExNjUsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"tsvb", + "name":"tsvb viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:21:32.694Z", + "id":"43921360-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:21:32.694Z", + "version":"WzExNjQsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"tsvb", + "name":"tsvb viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:21:25.541Z", + "id":"3f4e9d50-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:21:25.541Z", + "version":"WzExNjMsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"tsvb", + "name":"tsvb viz" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:21:16.768Z", + "id":"3a13f600-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:21:16.768Z", + "version":"WzExNjIsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test B" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:20:05.809Z", + "id":"0fc87a10-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:20:05.809Z", + "version":"WzExNTMsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test B" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:20:01.643Z", + "id":"0d4ccbb0-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:20:01.643Z", + "version":"WzExNTIsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test B" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:19:59.115Z", + "id":"0bcb0db0-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:19:59.115Z", + "version":"WzExNTEsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test B" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:19:57.114Z", + "id":"0a99b9a0-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:19:57.114Z", + "version":"WzExNTAsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test B" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:19:54.914Z", + "id":"094a0820-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:19:54.914Z", + "version":"WzExNDksMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test B" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:19:52.848Z", + "id":"080ec900-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:19:52.848Z", + "version":"WzExNDgsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test B" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:19:50.793Z", + "id":"06d53790-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:19:50.793Z", + "version":"WzExNDcsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test A" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:19:41.573Z", + "id":"01565b50-401d-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:19:41.573Z", + "version":"WzExNDYsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test A" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:19:37.791Z", + "id":"ff1544f0-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:19:37.791Z", + "version":"WzExNDUsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test A" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:19:35.809Z", + "id":"fde6d710-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:19:35.809Z", + "version":"WzExNDQsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test ABC", + "name":"test A" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:19:33.864Z", + "id":"fcbe0e80-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:19:33.864Z", + "version":"WzExNDMsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:18:08.259Z", + "id":"c9b7c530-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:18:08.259Z", + "version":"WzExNDIsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:18:05.901Z", + "id":"c84ff7d0-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:18:05.901Z", + "version":"WzExNDEsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:18:03.289Z", + "id":"c6c16890-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:18:03.289Z", + "version":"WzExNDAsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:18:01.153Z", + "id":"c57b7b10-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:18:01.153Z", + "version":"WzExMzksMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:59.441Z", + "id":"c4764010-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:59.441Z", + "version":"WzExMzgsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:57.633Z", + "id":"c3625f10-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:57.633Z", + "version":"WzExMzcsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:53.465Z", + "id":"c0e66290-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:53.465Z", + "version":"WzExMzYsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:51.117Z", + "id":"bf801bd0-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:51.117Z", + "version":"WzExMzUsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:49.071Z", + "id":"be47e9f0-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:49.071Z", + "version":"WzExMzQsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:46.863Z", + "id":"bcf6fff0-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:46.863Z", + "version":"WzExMzMsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:44.730Z", + "id":"bbb187a0-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:44.730Z", + "version":"WzExMzIsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:42.821Z", + "id":"ba8e3d50-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:42.821Z", + "version":"WzExMzEsMV0=" +} + + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:40.949Z", + "id":"b9709850-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:40.949Z", + "version":"WzExMzAsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test cases", + "name":"test cases" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:38.768Z", + "id":"b823cd00-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:38.768Z", + "version":"WzExMjksMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test news", + "name":"news" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:20.934Z", + "id":"ad828c60-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:20.934Z", + "version":"WzExMjgsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test news", + "name":"news" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:18.720Z", + "id":"ac30b800-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:18.720Z", + "version":"WzExMjcsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test news", + "name":"news" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:16.559Z", + "id":"aae6f9f0-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:16.559Z", + "version":"WzExMjYsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test news", + "name":"news" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:14.212Z", + "id":"a980da40-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:14.212Z", + "version":"WzExMjUsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test news", + "name":"news" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:17:11.174Z", + "id":"a7b14a60-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:17:11.174Z", + "version":"WzExMjQsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test news", + "name":"news_2" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:16:55.184Z", + "id":"9e296900-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:16:55.184Z", + "version":"WzExMjMsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test news", + "name":"news_1" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:16:44.460Z", + "id":"97c50ec0-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:16:44.460Z", + "version":"WzExMjIsMV0=" +} + +{ + "attributes":{ + "color":"#e0469e", + "description":"test news", + "name":"news" + }, + "coreMigrationVersion":"8.8.0", + "created_at":"2023-08-21T12:15:58.025Z", + "id":"7c17a390-401c-11ee-b3b5-c370b5546d0e", + "managed":false, + "references":[], + "type":"tag", + "typeMigrationVersion":"8.0.0", + "updated_at":"2023-08-21T12:15:58.025Z", + "version":"WzExMTMsMV0=" +} diff --git a/x-pack/plugins/actions/common/routes/connector/apis/connector_types/index.ts b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/index.ts new file mode 100644 index 0000000000000..b4d93fc1be5e6 --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { connectorTypesQuerySchema } from './schemas/latest'; +export type { ConnectorTypesRequestQuery } from './types/latest'; + +export { connectorTypesQuerySchema as connectorTypesQuerySchemaV1 } from './schemas/v1'; +export type { ConnectorTypesRequestQuery as ConnectorTypesRequestQueryV1 } from './types/v1'; diff --git a/x-pack/plugins/actions/common/routes/connector/apis/connector_types/schemas/latest.ts b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/schemas/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/schemas/latest.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './v1'; diff --git a/x-pack/plugins/actions/common/routes/connector/apis/connector_types/schemas/v1.ts b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/schemas/v1.ts new file mode 100644 index 0000000000000..bdbc01efc4b7a --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/schemas/v1.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; + +export const connectorTypesQuerySchema = schema.object({ + feature_id: schema.maybe(schema.string()), +}); diff --git a/x-pack/plugins/actions/common/routes/connector/apis/connector_types/types/latest.ts b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/types/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/types/latest.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './v1'; diff --git a/x-pack/plugins/actions/common/routes/connector/apis/connector_types/types/v1.ts b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/types/v1.ts new file mode 100644 index 0000000000000..cef43f8b41b18 --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/apis/connector_types/types/v1.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { TypeOf } from '@kbn/config-schema'; +import { connectorTypesQuerySchemaV1 } from '..'; + +export type ConnectorTypesRequestQuery = TypeOf; diff --git a/x-pack/plugins/actions/common/routes/connector/response/index.ts b/x-pack/plugins/actions/common/routes/connector/response/index.ts index cfc4d4a4a0098..99d08664c96a4 100644 --- a/x-pack/plugins/actions/common/routes/connector/response/index.ts +++ b/x-pack/plugins/actions/common/routes/connector/response/index.ts @@ -8,6 +8,7 @@ // Latest export type { ConnectorResponse, ActionTypeConfig } from './types/latest'; export { connectorResponseSchema } from './schemas/latest'; +export { connectorTypesResponseSchema } from './schemas/latest'; // v1 export type { @@ -15,3 +16,5 @@ export type { ActionTypeConfig as ActionTypeConfigV1, } from './types/v1'; export { connectorResponseSchema as connectorResponseSchemaV1 } from './schemas/v1'; +export type { ConnectorTypesResponse as ConnectorTypesResponseV1 } from './types/v1'; +export { connectorTypesResponseSchema as connectorTypesResponseSchemaV1 } from './schemas/v1'; diff --git a/x-pack/plugins/actions/common/routes/connector/response/schemas/latest.ts b/x-pack/plugins/actions/common/routes/connector/response/schemas/latest.ts index 96d490935d339..dbb5659baf8c4 100644 --- a/x-pack/plugins/actions/common/routes/connector/response/schemas/latest.ts +++ b/x-pack/plugins/actions/common/routes/connector/response/schemas/latest.ts @@ -6,3 +6,4 @@ */ export { connectorResponseSchema } from './v1'; +export { connectorTypesResponseSchema } from './v1'; diff --git a/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts b/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts index 6726aa740cf87..4f8be5b0f344f 100644 --- a/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts +++ b/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.ts @@ -18,3 +18,21 @@ export const connectorResponseSchema = schema.object({ is_system_action: schema.boolean(), referenced_by_count: schema.number(), }); + +export const connectorTypesResponseSchema = schema.object({ + id: schema.string(), + name: schema.string(), + enabled: schema.boolean(), + enabled_in_config: schema.boolean(), + enabled_in_license: schema.boolean(), + minimum_license_required: schema.oneOf([ + schema.literal('basic'), + schema.literal('standard'), + schema.literal('gold'), + schema.literal('platinum'), + schema.literal('enterprise'), + schema.literal('trial'), + ]), + supported_feature_ids: schema.arrayOf(schema.string()), + is_system_action_type: schema.boolean(), +}); diff --git a/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts b/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts index 9f49c048f92bf..5aed107c6f4f6 100644 --- a/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts +++ b/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts @@ -6,7 +6,7 @@ */ import { TypeOf } from '@kbn/config-schema'; -import { connectorResponseSchemaV1 } from '..'; +import { connectorResponseSchemaV1, connectorTypesResponseSchemaV1 } from '..'; export type ActionTypeConfig = Record; type ConnectorResponseSchemaType = TypeOf; @@ -22,3 +22,15 @@ export interface ConnectorResponse; +export interface ConnectorTypesResponse { + id: ConnectorTypesResponseSchemaType['id']; + name: ConnectorTypesResponseSchemaType['name']; + enabled: ConnectorTypesResponseSchemaType['enabled']; + enabled_in_config: ConnectorTypesResponseSchemaType['enabled_in_config']; + enabled_in_license: ConnectorTypesResponseSchemaType['enabled_in_license']; + minimum_license_required: ConnectorTypesResponseSchemaType['minimum_license_required']; + supported_feature_ids: ConnectorTypesResponseSchemaType['supported_feature_ids']; + is_system_action_type: ConnectorTypesResponseSchemaType['is_system_action_type']; +} diff --git a/x-pack/plugins/actions/server/actions_client.mock.ts b/x-pack/plugins/actions/server/actions_client/actions_client.mock.ts similarity index 97% rename from x-pack/plugins/actions/server/actions_client.mock.ts rename to x-pack/plugins/actions/server/actions_client/actions_client.mock.ts index 3fb08e5008793..5a369272617a2 100644 --- a/x-pack/plugins/actions/server/actions_client.mock.ts +++ b/x-pack/plugins/actions/server/actions_client/actions_client.mock.ts @@ -21,7 +21,6 @@ const createActionsClientMock = () => { getBulk: jest.fn(), getOAuthAccessToken: jest.fn(), execute: jest.fn(), - enqueueExecution: jest.fn(), ephemeralEnqueuedExecution: jest.fn(), bulkEnqueueExecution: jest.fn(), listTypes: jest.fn(), diff --git a/x-pack/plugins/actions/server/actions_client/actions_client.test.ts b/x-pack/plugins/actions/server/actions_client/actions_client.test.ts index 94adb4a6205c2..fa7410bb71178 100644 --- a/x-pack/plugins/actions/server/actions_client/actions_client.test.ts +++ b/x-pack/plugins/actions/server/actions_client/actions_client.test.ts @@ -97,7 +97,6 @@ const unsecuredSavedObjectsClient = savedObjectsClientMock.create(); const scopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); const actionExecutor = actionExecutorMock.create(); const authorization = actionsAuthorizationMock.create(); -const executionEnqueuer = jest.fn(); const ephemeralExecutionEnqueuer = jest.fn(); const bulkExecutionEnqueuer = jest.fn(); const request = httpServerMock.createKibanaRequest(); @@ -144,7 +143,6 @@ beforeEach(() => { kibanaIndices, inMemoryConnectors: [], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -612,7 +610,6 @@ describe('create()', () => { kibanaIndices, inMemoryConnectors: [], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -739,7 +736,6 @@ describe('create()', () => { ], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -802,7 +798,6 @@ describe('create()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -864,7 +859,6 @@ describe('get()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -902,7 +896,6 @@ describe('get()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -960,7 +953,6 @@ describe('get()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1004,7 +996,6 @@ describe('get()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1127,7 +1118,6 @@ describe('get()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1172,7 +1162,6 @@ describe('get()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1207,7 +1196,6 @@ describe('get()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1279,7 +1267,6 @@ describe('getBulk()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1418,7 +1405,6 @@ describe('getBulk()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1514,7 +1500,6 @@ describe('getBulk()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1589,7 +1574,6 @@ describe('getBulk()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1675,7 +1659,6 @@ describe('getOAuthAccessToken()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2058,7 +2041,6 @@ describe('delete()', () => { }, ], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2095,7 +2077,6 @@ describe('delete()', () => { }, ], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2611,7 +2592,6 @@ describe('update()', () => { }, ], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2655,7 +2635,6 @@ describe('update()', () => { }, ], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2764,7 +2743,6 @@ describe('execute()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2829,7 +2807,6 @@ describe('execute()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2893,7 +2870,6 @@ describe('execute()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3029,85 +3005,6 @@ describe('execute()', () => { }); }); -describe('enqueueExecution()', () => { - describe('authorization', () => { - test('ensures user is authorised to excecute actions', async () => { - (getAuthorizationModeBySource as jest.Mock).mockImplementationOnce(() => { - return AuthorizationMode.RBAC; - }); - await actionsClient.enqueueExecution({ - id: uuidv4(), - params: {}, - spaceId: 'default', - executionId: '123abc', - apiKey: null, - source: asHttpRequestExecutionSource(request), - }); - expect(authorization.ensureAuthorized).toHaveBeenCalledWith({ - operation: 'execute', - }); - }); - - test('throws when user is not authorised to create the type of action', async () => { - (getAuthorizationModeBySource as jest.Mock).mockImplementationOnce(() => { - return AuthorizationMode.RBAC; - }); - authorization.ensureAuthorized.mockRejectedValue( - new Error(`Unauthorized to execute all actions`) - ); - - await expect( - actionsClient.enqueueExecution({ - id: uuidv4(), - params: {}, - spaceId: 'default', - executionId: '123abc', - apiKey: null, - source: asHttpRequestExecutionSource(request), - }) - ).rejects.toMatchInlineSnapshot(`[Error: Unauthorized to execute all actions]`); - - expect(authorization.ensureAuthorized).toHaveBeenCalledWith({ - operation: 'execute', - }); - }); - - test('tracks legacy RBAC', async () => { - (getAuthorizationModeBySource as jest.Mock).mockImplementationOnce(() => { - return AuthorizationMode.Legacy; - }); - - await actionsClient.enqueueExecution({ - id: uuidv4(), - params: {}, - spaceId: 'default', - executionId: '123abc', - apiKey: null, - source: asHttpRequestExecutionSource(request), - }); - - expect(trackLegacyRBACExemption as jest.Mock).toBeCalledWith( - 'enqueueExecution', - mockUsageCounter - ); - }); - }); - - test('calls the executionEnqueuer with the appropriate parameters', async () => { - const opts = { - id: uuidv4(), - params: { baz: false }, - spaceId: 'default', - executionId: '123abc', - apiKey: Buffer.from('123:abc').toString('base64'), - source: asHttpRequestExecutionSource(request), - }; - await expect(actionsClient.enqueueExecution(opts)).resolves.toMatchInlineSnapshot(`undefined`); - - expect(executionEnqueuer).toHaveBeenCalledWith(unsecuredSavedObjectsClient, opts); - }); -}); - describe('bulkEnqueueExecution()', () => { describe('authorization', () => { test('ensures user is authorised to excecute actions', async () => { @@ -3233,172 +3130,6 @@ describe('bulkEnqueueExecution()', () => { }); }); -describe('listType()', () => { - it('filters action types by feature ID', async () => { - mockedLicenseState.isLicenseValidForActionType.mockReturnValue({ isValid: true }); - - actionTypeRegistry.register({ - id: 'my-action-type', - name: 'My action type', - minimumLicenseRequired: 'basic', - supportedFeatureIds: ['alerting'], - validate: { - config: { schema: schema.object({}) }, - secrets: { schema: schema.object({}) }, - params: { schema: schema.object({}) }, - }, - executor, - }); - - actionTypeRegistry.register({ - id: 'my-action-type-2', - name: 'My action type 2', - minimumLicenseRequired: 'basic', - supportedFeatureIds: ['cases'], - validate: { - config: { schema: schema.object({}) }, - secrets: { schema: schema.object({}) }, - params: { schema: schema.object({}) }, - }, - executor, - }); - - expect(await actionsClient.listTypes({ featureId: 'alerting' })).toEqual([ - { - id: 'my-action-type', - name: 'My action type', - minimumLicenseRequired: 'basic', - enabled: true, - enabledInConfig: true, - enabledInLicense: true, - supportedFeatureIds: ['alerting'], - isSystemActionType: false, - }, - ]); - }); - - it('filters out system action types when not defining options', async () => { - mockedLicenseState.isLicenseValidForActionType.mockReturnValue({ isValid: true }); - - actionTypeRegistry.register({ - id: 'my-action-type', - name: 'My action type', - minimumLicenseRequired: 'basic', - supportedFeatureIds: ['alerting'], - validate: { - config: { schema: schema.object({}) }, - secrets: { schema: schema.object({}) }, - params: { schema: schema.object({}) }, - }, - executor, - }); - - actionTypeRegistry.register({ - id: 'my-action-type-2', - name: 'My action type 2', - minimumLicenseRequired: 'basic', - supportedFeatureIds: ['cases'], - validate: { - config: { schema: schema.object({}) }, - secrets: { schema: schema.object({}) }, - params: { schema: schema.object({}) }, - }, - executor, - }); - - actionTypeRegistry.register({ - id: '.cases', - name: 'Cases', - minimumLicenseRequired: 'platinum', - supportedFeatureIds: ['alerting'], - validate: { - config: { schema: schema.object({}) }, - secrets: { schema: schema.object({}) }, - params: { schema: schema.object({}) }, - }, - isSystemActionType: true, - executor, - }); - - expect(await actionsClient.listTypes()).toEqual([ - { - id: 'my-action-type', - name: 'My action type', - minimumLicenseRequired: 'basic', - enabled: true, - enabledInConfig: true, - enabledInLicense: true, - supportedFeatureIds: ['alerting'], - isSystemActionType: false, - }, - { - id: 'my-action-type-2', - name: 'My action type 2', - isSystemActionType: false, - minimumLicenseRequired: 'basic', - supportedFeatureIds: ['cases'], - enabled: true, - enabledInConfig: true, - enabledInLicense: true, - }, - ]); - }); - - it('return system action types when defining options', async () => { - mockedLicenseState.isLicenseValidForActionType.mockReturnValue({ isValid: true }); - - actionTypeRegistry.register({ - id: 'my-action-type', - name: 'My action type', - minimumLicenseRequired: 'basic', - supportedFeatureIds: ['alerting'], - validate: { - config: { schema: schema.object({}) }, - secrets: { schema: schema.object({}) }, - params: { schema: schema.object({}) }, - }, - executor, - }); - - actionTypeRegistry.register({ - id: '.cases', - name: 'Cases', - minimumLicenseRequired: 'platinum', - supportedFeatureIds: ['alerting'], - validate: { - config: { schema: schema.object({}) }, - secrets: { schema: schema.object({}) }, - params: { schema: schema.object({}) }, - }, - isSystemActionType: true, - executor, - }); - - expect(await actionsClient.listTypes({ includeSystemActionTypes: true })).toEqual([ - { - id: 'my-action-type', - name: 'My action type', - minimumLicenseRequired: 'basic', - enabled: true, - enabledInConfig: true, - enabledInLicense: true, - supportedFeatureIds: ['alerting'], - isSystemActionType: false, - }, - { - id: '.cases', - name: 'Cases', - isSystemActionType: true, - minimumLicenseRequired: 'platinum', - supportedFeatureIds: ['alerting'], - enabled: true, - enabledInConfig: true, - enabledInLicense: true, - }, - ]); - }); -}); - describe('isActionTypeEnabled()', () => { const fooActionType: ActionType = { id: 'foo', @@ -3442,7 +3173,6 @@ describe('isPreconfigured()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3493,7 +3223,6 @@ describe('isPreconfigured()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3546,7 +3275,6 @@ describe('isSystemAction()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3597,7 +3325,6 @@ describe('isSystemAction()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, diff --git a/x-pack/plugins/actions/server/actions_client/actions_client.ts b/x-pack/plugins/actions/server/actions_client/actions_client.ts index 9fbf7c988c8f0..392b5ec7354b6 100644 --- a/x-pack/plugins/actions/server/actions_client/actions_client.ts +++ b/x-pack/plugins/actions/server/actions_client/actions_client.ts @@ -25,9 +25,10 @@ import { RunNowResult } from '@kbn/task-manager-plugin/server'; import { IEventLogClient } from '@kbn/event-log-plugin/server'; import { KueryNode } from '@kbn/es-query'; import { FindConnectorResult } from '../application/connector/types'; +import { ConnectorType } from '../application/connector/types'; import { getAll } from '../application/connector/methods/get_all'; +import { listTypes } from '../application/connector/methods/list_types'; import { - ActionType, GetGlobalExecutionKPIParams, GetGlobalExecutionLogParams, IExecutionLogResult, @@ -48,7 +49,6 @@ import { ActionTypeExecutorResult, ConnectorTokenClientContract, } from '../types'; - import { PreconfiguredActionDisabledModificationError } from '../lib/errors/preconfigured_action_disabled_modification'; import { ExecuteOptions } from '../lib/action_executor'; import { @@ -88,6 +88,7 @@ import { getExecutionLogAggregation, } from '../lib/get_execution_log_aggregation'; import { connectorFromSavedObject, isConnectorDeprecated } from '../application/connector/lib'; +import { ListTypesParams } from '../application/connector/methods/list_types/types'; interface ActionUpdate { name: string; @@ -104,7 +105,7 @@ export interface CreateOptions { options?: { id?: string }; } -interface ConstructorOptions { +export interface ConstructorOptions { logger: Logger; kibanaIndices: string[]; scopedClusterClient: IScopedClusterClient; @@ -112,7 +113,6 @@ interface ConstructorOptions { unsecuredSavedObjectsClient: SavedObjectsClientContract; inMemoryConnectors: InMemoryConnector[]; actionExecutor: ActionExecutorContract; - executionEnqueuer: ExecutionEnqueuer; ephemeralExecutionEnqueuer: ExecutionEnqueuer; bulkExecutionEnqueuer: BulkExecutionEnqueuer; request: KibanaRequest; @@ -128,11 +128,6 @@ export interface UpdateOptions { action: ActionUpdate; } -interface ListTypesOptions { - featureId?: string; - includeSystemActionTypes?: boolean; -} - export interface ActionsClientContext { logger: Logger; kibanaIndices: string[]; @@ -143,7 +138,6 @@ export interface ActionsClientContext { actionExecutor: ActionExecutorContract; request: KibanaRequest; authorization: ActionsAuthorization; - executionEnqueuer: ExecutionEnqueuer; ephemeralExecutionEnqueuer: ExecutionEnqueuer; bulkExecutionEnqueuer: BulkExecutionEnqueuer; auditLogger?: AuditLogger; @@ -163,7 +157,6 @@ export class ActionsClient { unsecuredSavedObjectsClient, inMemoryConnectors, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -181,7 +174,6 @@ export class ActionsClient { kibanaIndices, inMemoryConnectors, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -774,25 +766,6 @@ export class ActionsClient { }); } - public async enqueueExecution(options: EnqueueExecutionOptions): Promise { - const { source } = options; - if ( - (await getAuthorizationModeBySource(this.context.unsecuredSavedObjectsClient, source)) === - AuthorizationMode.RBAC - ) { - /** - * For scheduled executions the additional authorization check - * for system actions (kibana privileges) will be performed - * inside the ActionExecutor at execution time - */ - - await this.context.authorization.ensureAuthorized({ operation: 'execute' }); - } else { - trackLegacyRBACExemption('enqueueExecution', this.context.usageCounter); - } - return this.context.executionEnqueuer(this.context.unsecuredSavedObjectsClient, options); - } - public async bulkEnqueueExecution(options: EnqueueExecutionOptions[]): Promise { const sources: Array> = []; options.forEach((option) => { @@ -839,21 +812,11 @@ export class ActionsClient { ); } - /** - * Return all available action types - * expect system action types - */ public async listTypes({ featureId, includeSystemActionTypes = false, - }: ListTypesOptions = {}): Promise { - const actionTypes = this.context.actionTypeRegistry.list(featureId); - - const filteredActionTypes = includeSystemActionTypes - ? actionTypes - : actionTypes.filter((actionType) => !Boolean(actionType.isSystemActionType)); - - return filteredActionTypes; + }: ListTypesParams = {}): Promise { + return listTypes(this.context, { featureId, includeSystemActionTypes }); } public isActionTypeEnabled( diff --git a/x-pack/plugins/actions/server/application/connector/methods/get_all/get_all.test.ts b/x-pack/plugins/actions/server/application/connector/methods/get_all/get_all.test.ts index 938961f5f38f5..7e2ceb5b653c8 100644 --- a/x-pack/plugins/actions/server/application/connector/methods/get_all/get_all.test.ts +++ b/x-pack/plugins/actions/server/application/connector/methods/get_all/get_all.test.ts @@ -67,7 +67,6 @@ const unsecuredSavedObjectsClient = savedObjectsClientMock.create(); const scopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); const actionExecutor = actionExecutorMock.create(); const authorization = actionsAuthorizationMock.create(); -const executionEnqueuer = jest.fn(); const ephemeralExecutionEnqueuer = jest.fn(); const bulkExecutionEnqueuer = jest.fn(); const request = httpServerMock.createKibanaRequest(); @@ -93,7 +92,6 @@ describe('getAll()', () => { kibanaIndices, inMemoryConnectors: [], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -149,7 +147,6 @@ describe('getAll()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -294,7 +291,6 @@ describe('getAll()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -398,7 +394,6 @@ describe('getAll()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -504,7 +499,6 @@ describe('getAll()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, diff --git a/x-pack/plugins/security_solution/server/lib/app_features/index.ts b/x-pack/plugins/actions/server/application/connector/methods/list_types/index.ts similarity index 84% rename from x-pack/plugins/security_solution/server/lib/app_features/index.ts rename to x-pack/plugins/actions/server/application/connector/methods/list_types/index.ts index 5f30b21f9c862..e46209cd26fba 100644 --- a/x-pack/plugins/security_solution/server/lib/app_features/index.ts +++ b/x-pack/plugins/actions/server/application/connector/methods/list_types/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { AppFeatures } from './app_features'; +export { listTypes } from './list_types'; diff --git a/x-pack/plugins/actions/server/application/connector/methods/list_types/list_types.test.ts b/x-pack/plugins/actions/server/application/connector/methods/list_types/list_types.test.ts new file mode 100644 index 0000000000000..9ff5e05d45506 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/list_types/list_types.test.ts @@ -0,0 +1,235 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { actionsConfigMock } from '../../../../actions_config.mock'; +import { ActionTypeRegistry, ActionTypeRegistryOpts } from '../../../../action_type_registry'; +import { ActionsAuthorization } from '../../../../authorization/actions_authorization'; +import { ActionExecutor, ILicenseState, TaskRunnerFactory } from '../../../../lib'; +import { actionExecutorMock } from '../../../../lib/action_executor.mock'; +import { connectorTokenClientMock } from '../../../../lib/connector_token_client.mock'; +import { licenseStateMock } from '../../../../lib/license_state.mock'; +import { actionsAuthorizationMock } from '../../../../mocks'; +import { inMemoryMetricsMock } from '../../../../monitoring/in_memory_metrics.mock'; +import { schema } from '@kbn/config-schema'; +import { + httpServerMock, + loggingSystemMock, + elasticsearchServiceMock, + savedObjectsClientMock, +} from '@kbn/core/server/mocks'; +import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; +import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; +import { ActionsClient } from '../../../../actions_client/actions_client'; +import { ExecutorType } from '../../../../types'; + +let mockedLicenseState: jest.Mocked; +let actionTypeRegistryParams: ActionTypeRegistryOpts; +let actionTypeRegistry: ActionTypeRegistry; + +const executor: ExecutorType<{}, {}, {}, void> = async (options) => { + return { status: 'ok', actionId: options.actionId }; +}; + +describe('listTypes()', () => { + let actionsClient: ActionsClient; + + beforeEach(async () => { + jest.resetAllMocks(); + mockedLicenseState = licenseStateMock.create(); + actionTypeRegistryParams = { + licensing: licensingMock.createSetup(), + taskManager: taskManagerMock.createSetup(), + taskRunnerFactory: new TaskRunnerFactory( + new ActionExecutor({ isESOCanEncrypt: true }), + inMemoryMetricsMock.create() + ), + actionsConfigUtils: actionsConfigMock.create(), + licenseState: mockedLicenseState, + inMemoryConnectors: [], + }; + actionTypeRegistry = new ActionTypeRegistry(actionTypeRegistryParams); + actionsClient = new ActionsClient({ + logger: loggingSystemMock.create().get(), + kibanaIndices: ['.kibana'], + scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(), + actionTypeRegistry, + unsecuredSavedObjectsClient: savedObjectsClientMock.create(), + inMemoryConnectors: [], + actionExecutor: actionExecutorMock.create(), + ephemeralExecutionEnqueuer: jest.fn(), + bulkExecutionEnqueuer: jest.fn(), + request: httpServerMock.createKibanaRequest(), + authorization: actionsAuthorizationMock.create() as unknown as ActionsAuthorization, + connectorTokenClient: connectorTokenClientMock.create(), + getEventLogClient: jest.fn(), + }); + }); + + it('filters action types by feature ID', async () => { + mockedLicenseState.isLicenseValidForActionType.mockReturnValue({ isValid: true }); + + actionTypeRegistry.register({ + id: 'my-action-type', + name: 'My action type', + minimumLicenseRequired: 'basic', + supportedFeatureIds: ['alerting'], + validate: { + config: { schema: schema.object({}) }, + secrets: { schema: schema.object({}) }, + params: { schema: schema.object({}) }, + }, + executor, + }); + + actionTypeRegistry.register({ + id: 'my-action-type-2', + name: 'My action type 2', + minimumLicenseRequired: 'basic', + supportedFeatureIds: ['cases'], + validate: { + config: { schema: schema.object({}) }, + secrets: { schema: schema.object({}) }, + params: { schema: schema.object({}) }, + }, + executor, + }); + + expect(await actionsClient.listTypes({ featureId: 'alerting' })).toEqual([ + { + id: 'my-action-type', + name: 'My action type', + minimumLicenseRequired: 'basic', + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + supportedFeatureIds: ['alerting'], + isSystemActionType: false, + }, + ]); + }); + + it('filters out system action types when not defining options', async () => { + mockedLicenseState.isLicenseValidForActionType.mockReturnValue({ isValid: true }); + + actionTypeRegistry.register({ + id: 'my-action-type', + name: 'My action type', + minimumLicenseRequired: 'basic', + supportedFeatureIds: ['alerting'], + validate: { + config: { schema: schema.object({}) }, + secrets: { schema: schema.object({}) }, + params: { schema: schema.object({}) }, + }, + executor, + }); + + actionTypeRegistry.register({ + id: 'my-action-type-2', + name: 'My action type 2', + minimumLicenseRequired: 'basic', + supportedFeatureIds: ['cases'], + validate: { + config: { schema: schema.object({}) }, + secrets: { schema: schema.object({}) }, + params: { schema: schema.object({}) }, + }, + executor, + }); + + actionTypeRegistry.register({ + id: '.cases', + name: 'Cases', + minimumLicenseRequired: 'platinum', + supportedFeatureIds: ['alerting'], + validate: { + config: { schema: schema.object({}) }, + secrets: { schema: schema.object({}) }, + params: { schema: schema.object({}) }, + }, + isSystemActionType: true, + executor, + }); + + expect(await actionsClient.listTypes({})).toEqual([ + { + id: 'my-action-type', + name: 'My action type', + minimumLicenseRequired: 'basic', + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + supportedFeatureIds: ['alerting'], + isSystemActionType: false, + }, + { + id: 'my-action-type-2', + name: 'My action type 2', + isSystemActionType: false, + minimumLicenseRequired: 'basic', + supportedFeatureIds: ['cases'], + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + }, + ]); + }); + + it('return system action types when defining options', async () => { + mockedLicenseState.isLicenseValidForActionType.mockReturnValue({ isValid: true }); + + actionTypeRegistry.register({ + id: 'my-action-type', + name: 'My action type', + minimumLicenseRequired: 'basic', + supportedFeatureIds: ['alerting'], + validate: { + config: { schema: schema.object({}) }, + secrets: { schema: schema.object({}) }, + params: { schema: schema.object({}) }, + }, + executor, + }); + + actionTypeRegistry.register({ + id: '.cases', + name: 'Cases', + minimumLicenseRequired: 'platinum', + supportedFeatureIds: ['alerting'], + validate: { + config: { schema: schema.object({}) }, + secrets: { schema: schema.object({}) }, + params: { schema: schema.object({}) }, + }, + isSystemActionType: true, + executor, + }); + + expect(await actionsClient.listTypes({ includeSystemActionTypes: true })).toEqual([ + { + id: 'my-action-type', + name: 'My action type', + minimumLicenseRequired: 'basic', + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + supportedFeatureIds: ['alerting'], + isSystemActionType: false, + }, + { + id: '.cases', + name: 'Cases', + isSystemActionType: true, + minimumLicenseRequired: 'platinum', + supportedFeatureIds: ['alerting'], + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + }, + ]); + }); +}); diff --git a/x-pack/plugins/actions/server/application/connector/methods/list_types/list_types.ts b/x-pack/plugins/actions/server/application/connector/methods/list_types/list_types.ts new file mode 100644 index 0000000000000..cf218eba89355 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/list_types/list_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 Boom from '@hapi/boom'; +import { ActionsClientContext } from '../../../../actions_client'; +import { ConnectorType } from '../../types'; +import { listTypesParamsSchema } from './schemas'; +import { ListTypesParams } from './types'; + +export async function listTypes( + context: ActionsClientContext, + options: ListTypesParams +): Promise { + try { + listTypesParamsSchema.validate(options); + } catch (error) { + throw Boom.badRequest(`Error validating params - ${error.message}`); + } + + const { featureId, includeSystemActionTypes } = options; + + const connectorTypes = context.actionTypeRegistry.list(featureId); + + const filteredConnectorTypes = includeSystemActionTypes + ? connectorTypes + : connectorTypes.filter((type) => !Boolean(type.isSystemActionType)); + + return filteredConnectorTypes; +} diff --git a/x-pack/plugins/actions/server/application/connector/methods/list_types/schemas/index.ts b/x-pack/plugins/actions/server/application/connector/methods/list_types/schemas/index.ts new file mode 100644 index 0000000000000..afc2a2e545ac1 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/list_types/schemas/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { listTypesParamsSchema } from './list_types_params_schema'; diff --git a/x-pack/plugins/serverless_search/public/application/components/languages/utils.ts b/x-pack/plugins/actions/server/application/connector/methods/list_types/schemas/list_types_params_schema.ts similarity index 55% rename from x-pack/plugins/serverless_search/public/application/components/languages/utils.ts rename to x-pack/plugins/actions/server/application/connector/methods/list_types/schemas/list_types_params_schema.ts index f814c32537ebc..848345c79ff31 100644 --- a/x-pack/plugins/serverless_search/public/application/components/languages/utils.ts +++ b/x-pack/plugins/actions/server/application/connector/methods/list_types/schemas/list_types_params_schema.ts @@ -5,7 +5,9 @@ * 2.0. */ -import { LanguageDefinition } from '@kbn/search-api-panels'; -import { consoleDefinition } from './console'; +import { schema } from '@kbn/config-schema'; -export const showTryInConsole = (code: keyof LanguageDefinition) => code in consoleDefinition; +export const listTypesParamsSchema = schema.object({ + featureId: schema.maybe(schema.string()), + includeSystemActionTypes: schema.maybe(schema.boolean()), +}); diff --git a/x-pack/plugins/actions/server/application/connector/methods/list_types/types/index.ts b/x-pack/plugins/actions/server/application/connector/methods/list_types/types/index.ts new file mode 100644 index 0000000000000..763aba62f135d --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/list_types/types/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export type { ListTypesParams } from './list_types_params'; diff --git a/x-pack/plugins/actions/server/application/connector/methods/list_types/types/list_types_params.ts b/x-pack/plugins/actions/server/application/connector/methods/list_types/types/list_types_params.ts new file mode 100644 index 0000000000000..ac6d8b292964c --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/list_types/types/list_types_params.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 { TypeOf } from '@kbn/config-schema'; +import { listTypesParamsSchema } from '../schemas'; + +type ListTypesParamsType = TypeOf; + +export interface ListTypesParams { + featureId?: ListTypesParamsType['featureId']; + includeSystemActionTypes?: ListTypesParamsType['includeSystemActionTypes']; +} diff --git a/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts b/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.ts new file mode 100644 index 0000000000000..e5556ab5c4a33 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/schemas/connector_type_schema.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 { schema } from '@kbn/config-schema'; + +export const connectorTypeSchema = schema.object({ + id: schema.string(), + name: schema.string(), + enabled: schema.boolean(), + enabledInConfig: schema.boolean(), + enabledInLicense: schema.boolean(), + minimumLicenseRequired: schema.oneOf([ + schema.literal('basic'), + schema.literal('standard'), + schema.literal('gold'), + schema.literal('platinum'), + schema.literal('enterprise'), + schema.literal('trial'), + ]), + supportedFeatureIds: schema.arrayOf(schema.string()), + isSystemActionType: schema.boolean(), +}); diff --git a/x-pack/plugins/actions/server/application/connector/schemas/index.ts b/x-pack/plugins/actions/server/application/connector/schemas/index.ts index f2a1bc4c6096a..b3cfc462c4208 100644 --- a/x-pack/plugins/actions/server/application/connector/schemas/index.ts +++ b/x-pack/plugins/actions/server/application/connector/schemas/index.ts @@ -6,3 +6,4 @@ */ export * from './connector_schema'; +export * from './connector_type_schema'; diff --git a/x-pack/plugins/actions/server/application/connector/types/connector_type.ts b/x-pack/plugins/actions/server/application/connector/types/connector_type.ts new file mode 100644 index 0000000000000..64be01365a8ba --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/types/connector_type.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 { TypeOf } from '@kbn/config-schema'; +import { connectorTypeSchema } from '../schemas'; + +type ConnectorTypeSchemaType = TypeOf; + +export interface ConnectorType { + id: ConnectorTypeSchemaType['id']; + name: ConnectorTypeSchemaType['name']; + enabled: ConnectorTypeSchemaType['enabled']; + enabledInConfig: ConnectorTypeSchemaType['enabledInConfig']; + enabledInLicense: ConnectorTypeSchemaType['enabledInLicense']; + minimumLicenseRequired: ConnectorTypeSchemaType['minimumLicenseRequired']; + supportedFeatureIds: ConnectorTypeSchemaType['supportedFeatureIds']; + isSystemActionType: ConnectorTypeSchemaType['isSystemActionType']; +} diff --git a/x-pack/plugins/actions/server/application/connector/types/index.ts b/x-pack/plugins/actions/server/application/connector/types/index.ts index ab87e9a5baaad..973513ec7b5cb 100644 --- a/x-pack/plugins/actions/server/application/connector/types/index.ts +++ b/x-pack/plugins/actions/server/application/connector/types/index.ts @@ -6,3 +6,4 @@ */ export type { Connector, FindConnectorResult } from './connector'; +export type { ConnectorType } from './connector_type'; diff --git a/x-pack/plugins/actions/server/create_execute_function.test.ts b/x-pack/plugins/actions/server/create_execute_function.test.ts index fae2ca6c0f9d9..72903ca433b4e 100644 --- a/x-pack/plugins/actions/server/create_execute_function.test.ts +++ b/x-pack/plugins/actions/server/create_execute_function.test.ts @@ -8,10 +8,7 @@ import { KibanaRequest } from '@kbn/core/server'; import { v4 as uuidv4 } from 'uuid'; import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; -import { - createExecutionEnqueuerFunction, - createBulkExecutionEnqueuerFunction, -} from './create_execute_function'; +import { createBulkExecutionEnqueuerFunction } from './create_execute_function'; import { savedObjectsClientMock } from '@kbn/core/server/mocks'; import { actionTypeRegistryMock } from './action_type_registry.mock'; import { @@ -25,776 +22,6 @@ const request = {} as KibanaRequest; beforeEach(() => jest.resetAllMocks()); -describe('execute()', () => { - test('schedules the action with all given parameters', async () => { - const actionTypeRegistry = actionTypeRegistryMock.create(); - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - actionTypeRegistry, - isESOCanEncrypt: true, - inMemoryConnectors: [], - }); - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'mock-action', - }, - references: [], - }); - savedObjectsClient.create.mockResolvedValueOnce({ - id: '234', - type: 'action_task_params', - attributes: {}, - references: [], - }); - await executeFn(savedObjectsClient, { - id: '123', - params: { baz: false }, - spaceId: 'default', - executionId: '123abc', - apiKey: Buffer.from('123:abc').toString('base64'), - source: asHttpRequestExecutionSource(request), - }); - expect(mockTaskManager.schedule).toHaveBeenCalledTimes(1); - expect(mockTaskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "params": Object { - "actionTaskParamsId": "234", - "spaceId": "default", - }, - "scope": Array [ - "actions", - ], - "state": Object {}, - "taskType": "actions:mock-action", - }, - ] - `); - expect(savedObjectsClient.get).toHaveBeenCalledWith('action', '123'); - expect(savedObjectsClient.create).toHaveBeenCalledWith( - 'action_task_params', - { - actionId: '123', - params: { baz: false }, - executionId: '123abc', - source: 'HTTP_REQUEST', - apiKey: Buffer.from('123:abc').toString('base64'), - }, - { - references: [ - { - id: '123', - name: 'actionRef', - type: 'action', - }, - ], - } - ); - expect(actionTypeRegistry.isActionExecutable).toHaveBeenCalledWith('123', 'mock-action', { - notifyUsage: true, - }); - }); - - test('schedules the action with all given parameters and consumer', async () => { - const actionTypeRegistry = actionTypeRegistryMock.create(); - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - actionTypeRegistry, - isESOCanEncrypt: true, - inMemoryConnectors: [], - }); - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'mock-action', - }, - references: [], - }); - savedObjectsClient.create.mockResolvedValueOnce({ - id: '234', - type: 'action_task_params', - attributes: {}, - references: [], - }); - await executeFn(savedObjectsClient, { - id: '123', - params: { baz: false }, - spaceId: 'default', - executionId: '123abc', - consumer: 'test-consumer', - apiKey: Buffer.from('123:abc').toString('base64'), - source: asHttpRequestExecutionSource(request), - }); - expect(mockTaskManager.schedule).toHaveBeenCalledTimes(1); - expect(mockTaskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "params": Object { - "actionTaskParamsId": "234", - "spaceId": "default", - }, - "scope": Array [ - "actions", - ], - "state": Object {}, - "taskType": "actions:mock-action", - }, - ] - `); - expect(savedObjectsClient.get).toHaveBeenCalledWith('action', '123'); - expect(savedObjectsClient.create).toHaveBeenCalledWith( - 'action_task_params', - { - actionId: '123', - params: { baz: false }, - executionId: '123abc', - consumer: 'test-consumer', - source: 'HTTP_REQUEST', - apiKey: Buffer.from('123:abc').toString('base64'), - }, - { - references: [ - { - id: '123', - name: 'actionRef', - type: 'action', - }, - ], - } - ); - expect(actionTypeRegistry.isActionExecutable).toHaveBeenCalledWith('123', 'mock-action', { - notifyUsage: true, - }); - }); - - test('schedules the action with all given parameters and relatedSavedObjects', async () => { - const actionTypeRegistry = actionTypeRegistryMock.create(); - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - actionTypeRegistry, - isESOCanEncrypt: true, - inMemoryConnectors: [], - }); - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'mock-action', - }, - references: [], - }); - savedObjectsClient.create.mockResolvedValueOnce({ - id: '234', - type: 'action_task_params', - attributes: {}, - references: [], - }); - await executeFn(savedObjectsClient, { - id: '123', - params: { baz: false }, - spaceId: 'default', - apiKey: Buffer.from('123:abc').toString('base64'), - source: asHttpRequestExecutionSource(request), - executionId: '123abc', - relatedSavedObjects: [ - { - id: 'some-id', - namespace: 'some-namespace', - type: 'some-type', - typeId: 'some-typeId', - }, - ], - }); - expect(savedObjectsClient.create).toHaveBeenCalledWith( - 'action_task_params', - { - actionId: '123', - params: { baz: false }, - apiKey: Buffer.from('123:abc').toString('base64'), - executionId: '123abc', - source: 'HTTP_REQUEST', - relatedSavedObjects: [ - { - id: 'related_some-type_0', - namespace: 'some-namespace', - type: 'some-type', - typeId: 'some-typeId', - }, - ], - }, - { - references: [ - { - id: '123', - name: 'actionRef', - type: 'action', - }, - { - id: 'some-id', - name: 'related_some-type_0', - type: 'some-type', - }, - ], - } - ); - }); - - test('schedules the action with all given parameters with a preconfigured action', async () => { - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - actionTypeRegistry: actionTypeRegistryMock.create(), - isESOCanEncrypt: true, - inMemoryConnectors: [ - { - id: '123', - actionTypeId: 'mock-action-preconfigured', - config: {}, - isPreconfigured: true, - isDeprecated: false, - isSystemAction: false, - name: 'x', - secrets: {}, - }, - ], - }); - const source = { type: 'alert', id: uuidv4() }; - - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'mock-action', - }, - references: [], - }); - savedObjectsClient.create.mockResolvedValueOnce({ - id: '234', - type: 'action_task_params', - attributes: {}, - references: [], - }); - await executeFn(savedObjectsClient, { - id: '123', - params: { baz: false }, - spaceId: 'default', - executionId: '123abc', - apiKey: Buffer.from('123:abc').toString('base64'), - source: asSavedObjectExecutionSource(source), - }); - expect(mockTaskManager.schedule).toHaveBeenCalledTimes(1); - expect(mockTaskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "params": Object { - "actionTaskParamsId": "234", - "spaceId": "default", - }, - "scope": Array [ - "actions", - ], - "state": Object {}, - "taskType": "actions:mock-action-preconfigured", - }, - ] - `); - expect(savedObjectsClient.get).not.toHaveBeenCalled(); - expect(savedObjectsClient.create).toHaveBeenCalledWith( - 'action_task_params', - { - actionId: '123', - params: { baz: false }, - executionId: '123abc', - source: 'SAVED_OBJECT', - apiKey: Buffer.from('123:abc').toString('base64'), - }, - { - references: [ - { - id: source.id, - name: 'source', - type: source.type, - }, - ], - } - ); - }); - - test('schedules the action with all given parameters with a system action', async () => { - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - actionTypeRegistry: actionTypeRegistryMock.create(), - isESOCanEncrypt: true, - inMemoryConnectors: [ - { - actionTypeId: 'test.system-action', - config: {}, - id: 'system-connector-test.system-action', - name: 'System action: test.system-action', - secrets: {}, - isPreconfigured: false, - isDeprecated: false, - isSystemAction: true, - }, - ], - }); - const source = { type: 'alert', id: uuidv4() }; - - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'test.system-action', - }, - references: [], - }); - - savedObjectsClient.create.mockResolvedValueOnce({ - id: '234', - type: 'action_task_params', - attributes: {}, - references: [], - }); - - await executeFn(savedObjectsClient, { - id: 'system-connector-test.system-action', - params: { baz: false }, - spaceId: 'default', - executionId: 'system-connector-.casesabc', - apiKey: Buffer.from('system-connector-test.system-action:abc').toString('base64'), - source: asSavedObjectExecutionSource(source), - }); - - expect(mockTaskManager.schedule).toHaveBeenCalledTimes(1); - expect(mockTaskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "params": Object { - "actionTaskParamsId": "234", - "spaceId": "default", - }, - "scope": Array [ - "actions", - ], - "state": Object {}, - "taskType": "actions:test.system-action", - }, - ] - `); - expect(savedObjectsClient.get).not.toHaveBeenCalled(); - expect(savedObjectsClient.create).toHaveBeenCalledWith( - 'action_task_params', - { - actionId: 'system-connector-test.system-action', - params: { baz: false }, - executionId: 'system-connector-.casesabc', - source: 'SAVED_OBJECT', - apiKey: Buffer.from('system-connector-test.system-action:abc').toString('base64'), - }, - { - references: [ - { - id: source.id, - name: 'source', - type: source.type, - }, - ], - } - ); - }); - - test('schedules the action with all given parameters with a preconfigured action and relatedSavedObjects', async () => { - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - actionTypeRegistry: actionTypeRegistryMock.create(), - isESOCanEncrypt: true, - inMemoryConnectors: [ - { - id: '123', - actionTypeId: 'mock-action-preconfigured', - config: {}, - isPreconfigured: true, - isDeprecated: false, - isSystemAction: false, - name: 'x', - secrets: {}, - }, - ], - }); - const source = { type: 'alert', id: uuidv4() }; - - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'mock-action', - }, - references: [], - }); - savedObjectsClient.create.mockResolvedValueOnce({ - id: '234', - type: 'action_task_params', - attributes: {}, - references: [], - }); - await executeFn(savedObjectsClient, { - id: '123', - params: { baz: false }, - spaceId: 'default', - apiKey: Buffer.from('123:abc').toString('base64'), - source: asSavedObjectExecutionSource(source), - executionId: '123abc', - relatedSavedObjects: [ - { - id: 'some-id', - namespace: 'some-namespace', - type: 'some-type', - typeId: 'some-typeId', - }, - ], - }); - expect(mockTaskManager.schedule).toHaveBeenCalledTimes(1); - expect(mockTaskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "params": Object { - "actionTaskParamsId": "234", - "spaceId": "default", - }, - "scope": Array [ - "actions", - ], - "state": Object {}, - "taskType": "actions:mock-action-preconfigured", - }, - ] - `); - expect(savedObjectsClient.get).not.toHaveBeenCalled(); - expect(savedObjectsClient.create).toHaveBeenCalledWith( - 'action_task_params', - { - actionId: '123', - params: { baz: false }, - apiKey: Buffer.from('123:abc').toString('base64'), - executionId: '123abc', - source: 'SAVED_OBJECT', - relatedSavedObjects: [ - { - id: 'related_some-type_0', - namespace: 'some-namespace', - type: 'some-type', - typeId: 'some-typeId', - }, - ], - }, - { - references: [ - { - id: source.id, - name: 'source', - type: source.type, - }, - { - id: 'some-id', - name: 'related_some-type_0', - type: 'some-type', - }, - ], - } - ); - }); - - test('schedules the action with all given parameters with a system action and relatedSavedObjects', async () => { - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - actionTypeRegistry: actionTypeRegistryMock.create(), - isESOCanEncrypt: true, - inMemoryConnectors: [ - { - actionTypeId: 'test.system-action', - config: {}, - id: 'system-connector-test.system-action', - name: 'System action: test.system-action', - secrets: {}, - isPreconfigured: false, - isDeprecated: false, - isSystemAction: true, - }, - ], - }); - const source = { type: 'alert', id: uuidv4() }; - - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'test.system-action', - }, - references: [], - }); - savedObjectsClient.create.mockResolvedValueOnce({ - id: '234', - type: 'action_task_params', - attributes: {}, - references: [], - }); - await executeFn(savedObjectsClient, { - id: 'system-connector-test.system-action', - params: { baz: false }, - spaceId: 'default', - apiKey: Buffer.from('system-connector-test.system-action:abc').toString('base64'), - source: asSavedObjectExecutionSource(source), - executionId: 'system-connector-.casesabc', - relatedSavedObjects: [ - { - id: 'some-id', - namespace: 'some-namespace', - type: 'some-type', - typeId: 'some-typeId', - }, - ], - }); - expect(mockTaskManager.schedule).toHaveBeenCalledTimes(1); - expect(mockTaskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "params": Object { - "actionTaskParamsId": "234", - "spaceId": "default", - }, - "scope": Array [ - "actions", - ], - "state": Object {}, - "taskType": "actions:test.system-action", - }, - ] - `); - expect(savedObjectsClient.get).not.toHaveBeenCalled(); - expect(savedObjectsClient.create).toHaveBeenCalledWith( - 'action_task_params', - { - actionId: 'system-connector-test.system-action', - params: { baz: false }, - apiKey: Buffer.from('system-connector-test.system-action:abc').toString('base64'), - executionId: 'system-connector-.casesabc', - source: 'SAVED_OBJECT', - relatedSavedObjects: [ - { - id: 'related_some-type_0', - namespace: 'some-namespace', - type: 'some-type', - typeId: 'some-typeId', - }, - ], - }, - { - references: [ - { - id: source.id, - name: 'source', - type: source.type, - }, - { - id: 'some-id', - name: 'related_some-type_0', - type: 'some-type', - }, - ], - } - ); - }); - - test('throws when passing isESOCanEncrypt with false as a value', async () => { - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - isESOCanEncrypt: false, - actionTypeRegistry: actionTypeRegistryMock.create(), - inMemoryConnectors: [], - }); - await expect( - executeFn(savedObjectsClient, { - id: '123', - params: { baz: false }, - spaceId: 'default', - executionId: '123abc', - apiKey: null, - source: asHttpRequestExecutionSource(request), - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` - ); - }); - - test('throws when isMissingSecrets is true for connector', async () => { - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - isESOCanEncrypt: true, - actionTypeRegistry: actionTypeRegistryMock.create(), - inMemoryConnectors: [], - }); - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - name: 'mock-action', - isMissingSecrets: true, - actionTypeId: 'mock-action', - }, - references: [], - }); - await expect( - executeFn(savedObjectsClient, { - id: '123', - params: { baz: false }, - spaceId: 'default', - executionId: '123abc', - apiKey: null, - source: asHttpRequestExecutionSource(request), - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Unable to execute action because no secrets are defined for the \\"mock-action\\" connector."` - ); - }); - - test('should ensure action type is enabled', async () => { - const mockedActionTypeRegistry = actionTypeRegistryMock.create(); - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - isESOCanEncrypt: true, - actionTypeRegistry: mockedActionTypeRegistry, - inMemoryConnectors: [], - }); - mockedActionTypeRegistry.ensureActionTypeEnabled.mockImplementation(() => { - throw new Error('Fail'); - }); - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'mock-action', - }, - references: [], - }); - - await expect( - executeFn(savedObjectsClient, { - id: '123', - params: { baz: false }, - spaceId: 'default', - executionId: '123abc', - apiKey: null, - source: asHttpRequestExecutionSource(request), - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"Fail"`); - }); - - test('should skip ensure action type if action type is preconfigured and license is valid', async () => { - const mockedActionTypeRegistry = actionTypeRegistryMock.create(); - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - isESOCanEncrypt: true, - actionTypeRegistry: mockedActionTypeRegistry, - inMemoryConnectors: [ - { - actionTypeId: 'mock-action', - config: {}, - id: 'my-slack1', - name: 'Slack #xyz', - secrets: {}, - isPreconfigured: true, - isSystemAction: false, - isDeprecated: false, - }, - ], - }); - mockedActionTypeRegistry.isActionExecutable.mockImplementation(() => true); - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'mock-action', - }, - references: [], - }); - savedObjectsClient.create.mockResolvedValueOnce({ - id: '234', - type: 'action_task_params', - attributes: {}, - references: [], - }); - - await executeFn(savedObjectsClient, { - id: '123', - params: { baz: false }, - spaceId: 'default', - executionId: '123abc', - apiKey: null, - source: asHttpRequestExecutionSource(request), - }); - - expect(mockedActionTypeRegistry.ensureActionTypeEnabled).not.toHaveBeenCalled(); - }); - - test('should ensure if a system action type is enabled', async () => { - const mockedActionTypeRegistry = actionTypeRegistryMock.create(); - const executeFn = createExecutionEnqueuerFunction({ - taskManager: mockTaskManager, - isESOCanEncrypt: true, - actionTypeRegistry: mockedActionTypeRegistry, - inMemoryConnectors: [ - { - actionTypeId: 'test.system-action', - config: {}, - id: 'system-connector-test.system-action', - name: 'System action: test.system-action', - secrets: {}, - isPreconfigured: false, - isDeprecated: false, - isSystemAction: true, - }, - ], - }); - - mockedActionTypeRegistry.ensureActionTypeEnabled.mockImplementation(() => { - throw new Error('Fail'); - }); - - savedObjectsClient.get.mockResolvedValueOnce({ - id: '123', - type: 'action', - attributes: { - actionTypeId: 'test.system-action', - }, - references: [], - }); - - savedObjectsClient.create.mockResolvedValueOnce({ - id: '234', - type: 'action_task_params', - attributes: {}, - references: [], - }); - - await expect( - executeFn(savedObjectsClient, { - id: 'system-connector-test.system-action', - params: { baz: false }, - spaceId: 'default', - executionId: 'system-connector-.test.system-action-abc', - apiKey: null, - source: asHttpRequestExecutionSource(request), - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"Fail"`); - - expect(mockedActionTypeRegistry.ensureActionTypeEnabled).toHaveBeenCalledWith( - 'test.system-action' - ); - }); -}); - describe('bulkExecute()', () => { test('schedules the action with all given parameters', async () => { const actionTypeRegistry = actionTypeRegistryMock.create(); diff --git a/x-pack/plugins/actions/server/create_execute_function.ts b/x-pack/plugins/actions/server/create_execute_function.ts index 6752b17fd5ffd..3b4233ddf5710 100644 --- a/x-pack/plugins/actions/server/create_execute_function.ts +++ b/x-pack/plugins/actions/server/create_execute_function.ts @@ -54,87 +54,6 @@ export type BulkExecutionEnqueuer = ( actionsToExectute: ExecuteOptions[] ) => Promise; -export function createExecutionEnqueuerFunction({ - taskManager, - actionTypeRegistry, - isESOCanEncrypt, - inMemoryConnectors, -}: CreateExecuteFunctionOptions): ExecutionEnqueuer { - return async function execute( - unsecuredSavedObjectsClient: SavedObjectsClientContract, - { - id, - params, - spaceId, - consumer, - source, - apiKey, - executionId, - relatedSavedObjects, - }: ExecuteOptions - ) { - if (!isESOCanEncrypt) { - throw new Error( - `Unable to execute action because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.` - ); - } - - const { action, isInMemory } = await getAction( - unsecuredSavedObjectsClient, - inMemoryConnectors, - id - ); - validateCanActionBeUsed(action); - - const { actionTypeId } = action; - if (!actionTypeRegistry.isActionExecutable(id, actionTypeId, { notifyUsage: true })) { - actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); - } - - // Get saved object references from action ID and relatedSavedObjects - const { references, relatedSavedObjectWithRefs } = extractSavedObjectReferences( - id, - isInMemory, - relatedSavedObjects - ); - const executionSourceReference = executionSourceAsSavedObjectReferences(source); - - const taskReferences = []; - if (executionSourceReference.references) { - taskReferences.push(...executionSourceReference.references); - } - if (references) { - taskReferences.push(...references); - } - - const actionTaskParamsRecord = await unsecuredSavedObjectsClient.create( - ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE, - { - actionId: id, - params, - apiKey, - executionId, - consumer, - relatedSavedObjects: relatedSavedObjectWithRefs, - ...(source ? { source: source.type } : {}), - }, - { - references: taskReferences, - } - ); - - await taskManager.schedule({ - taskType: `actions:${action.actionTypeId}`, - params: { - spaceId, - actionTaskParamsId: actionTaskParamsRecord.id, - }, - state: {}, - scope: ['actions'], - }); - }; -} - export function createBulkExecutionEnqueuerFunction({ taskManager, actionTypeRegistry, diff --git a/x-pack/plugins/actions/server/data/connector/search_connectors_so.ts b/x-pack/plugins/actions/server/data/connector/search_connectors_so.ts index b44b109e9265f..09d3ae3b532d9 100644 --- a/x-pack/plugins/actions/server/data/connector/search_connectors_so.ts +++ b/x-pack/plugins/actions/server/data/connector/search_connectors_so.ts @@ -14,6 +14,7 @@ export const searchConnectorsSo = async ({ }: SearchConnectorsSoParams) => { return scopedClusterClient.asInternalUser.search({ index: kibanaIndices, + ignore_unavailable: true, body: { aggs, size: 0, diff --git a/x-pack/plugins/actions/server/mocks.ts b/x-pack/plugins/actions/server/mocks.ts index 14ae64391177f..ad26114cf7d07 100644 --- a/x-pack/plugins/actions/server/mocks.ts +++ b/x-pack/plugins/actions/server/mocks.ts @@ -12,7 +12,7 @@ import { } from '@kbn/core/server/mocks'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { Logger } from '@kbn/core/server'; -import { actionsClientMock } from './actions_client.mock'; +import { actionsClientMock } from './actions_client/actions_client.mock'; import { PluginSetupContract, PluginStartContract, renderActionParameterTemplates } from './plugin'; import { Services } from './types'; import { actionsAuthorizationMock } from './authorization/actions_authorization.mock'; diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 122e3075ac0ac..b8b88b05049ca 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -42,10 +42,9 @@ import { MonitoringCollectionSetup } from '@kbn/monitoring-collection-plugin/ser import { ActionsConfig, getValidatedConfig } from './config'; import { resolveCustomHosts } from './lib/custom_host_settings'; -import { ActionsClient } from './actions_client'; +import { ActionsClient } from './actions_client/actions_client'; import { ActionTypeRegistry } from './action_type_registry'; import { - createExecutionEnqueuerFunction, createEphemeralExecutionEnqueuerFunction, createBulkExecutionEnqueuerFunction, } from './create_execute_function'; @@ -443,12 +442,6 @@ export class ActionsPlugin implements Plugin ({ verifyAccessAndContext: jest.fn(), diff --git a/x-pack/plugins/actions/server/routes/connector/list_types/index.ts b/x-pack/plugins/actions/server/routes/connector/list_types/index.ts new file mode 100644 index 0000000000000..668942c40ae90 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/list_types/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { listTypesRoute } from './list_types'; diff --git a/x-pack/plugins/actions/server/routes/connector_types.test.ts b/x-pack/plugins/actions/server/routes/connector/list_types/list_types.test.ts similarity index 91% rename from x-pack/plugins/actions/server/routes/connector_types.test.ts rename to x-pack/plugins/actions/server/routes/connector/list_types/list_types.test.ts index 4c5a7089b75c4..91419ac562324 100644 --- a/x-pack/plugins/actions/server/routes/connector_types.test.ts +++ b/x-pack/plugins/actions/server/routes/connector/list_types/list_types.test.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { connectorTypesRoute } from './connector_types'; import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../lib/license_state.mock'; -import { mockHandlerArguments } from './legacy/_mock_handler_arguments'; import { LicenseType } from '@kbn/licensing-plugin/server'; -import { actionsClientMock } from '../mocks'; -import { verifyAccessAndContext } from './verify_access_and_context'; +import { licenseStateMock } from '../../../lib/license_state.mock'; +import { mockHandlerArguments } from '../../legacy/_mock_handler_arguments'; +import { listTypesRoute } from './list_types'; +import { verifyAccessAndContext } from '../../verify_access_and_context'; +import { actionsClientMock } from '../../../mocks'; -jest.mock('./verify_access_and_context', () => ({ +jest.mock('../../verify_access_and_context', () => ({ verifyAccessAndContext: jest.fn(), })); @@ -22,12 +22,12 @@ beforeEach(() => { (verifyAccessAndContext as jest.Mock).mockImplementation((license, handler) => handler); }); -describe('connectorTypesRoute', () => { +describe('listTypesRoute', () => { it('lists action types with proper parameters', async () => { const licenseState = licenseStateMock.create(); const router = httpServiceMock.createRouter(); - connectorTypesRoute(router, licenseState); + listTypesRoute(router, licenseState); const [config, handler] = router.get.mock.calls[0]; @@ -89,7 +89,7 @@ describe('connectorTypesRoute', () => { const licenseState = licenseStateMock.create(); const router = httpServiceMock.createRouter(); - connectorTypesRoute(router, licenseState); + listTypesRoute(router, licenseState); const [config, handler] = router.get.mock.calls[0]; @@ -168,7 +168,7 @@ describe('connectorTypesRoute', () => { const licenseState = licenseStateMock.create(); const router = httpServiceMock.createRouter(); - connectorTypesRoute(router, licenseState); + listTypesRoute(router, licenseState); const [config, handler] = router.get.mock.calls[0]; @@ -211,7 +211,7 @@ describe('connectorTypesRoute', () => { throw new Error('OMG'); }); - connectorTypesRoute(router, licenseState); + listTypesRoute(router, licenseState); const [config, handler] = router.get.mock.calls[0]; diff --git a/x-pack/plugins/actions/server/routes/connector/list_types/list_types.ts b/x-pack/plugins/actions/server/routes/connector/list_types/list_types.ts new file mode 100644 index 0000000000000..078c51743c4d9 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/list_types/list_types.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IRouter } from '@kbn/core/server'; +import { ConnectorTypesResponseV1 } from '../../../../common/routes/connector/response'; +import { + connectorTypesQuerySchemaV1, + ConnectorTypesRequestQueryV1, +} from '../../../../common/routes/connector/apis/connector_types'; +import { transformListTypesResponseV1 } from './transforms'; +import { ActionsRequestHandlerContext } from '../../../types'; +import { BASE_ACTION_API_PATH } from '../../../../common'; +import { ILicenseState } from '../../../lib'; +import { verifyAccessAndContext } from '../../verify_access_and_context'; + +export const listTypesRoute = ( + router: IRouter, + licenseState: ILicenseState +) => { + router.get( + { + path: `${BASE_ACTION_API_PATH}/connector_types`, + validate: { + query: connectorTypesQuerySchemaV1, + }, + }, + router.handleLegacyErrors( + verifyAccessAndContext(licenseState, async function (context, req, res) { + const actionsClient = (await context.actions).getActionsClient(); + + // Assert versioned inputs + const query: ConnectorTypesRequestQueryV1 = req.query; + + const connectorTypes = await actionsClient.listTypes({ featureId: query?.feature_id }); + + const responseBody: ConnectorTypesResponseV1[] = + transformListTypesResponseV1(connectorTypes); + + return res.ok({ body: responseBody }); + }) + ) + ); +}; diff --git a/x-pack/plugins/actions/server/routes/connector/list_types/transforms/index.ts b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/index.ts new file mode 100644 index 0000000000000..35e5f1db443c2 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { transformListTypesResponse } from './transform_list_types_response/latest'; +export { transformListTypesResponse as transformListTypesResponseV1 } from './transform_list_types_response/v1'; diff --git a/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/latest.ts b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/latest.ts new file mode 100644 index 0000000000000..5fd887263233c --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/latest.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { transformListTypesResponse } from './v1'; diff --git a/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.ts new file mode 100644 index 0000000000000..e32bec2f9e1a1 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/list_types/transforms/transform_list_types_response/v1.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 { ConnectorType } from '../../../../../application/connector/types'; +import { ConnectorTypesResponseV1 } from '../../../../../../common/routes/connector/response'; + +export const transformListTypesResponse = ( + results: ConnectorType[] +): ConnectorTypesResponseV1[] => { + return results.map( + ({ + id, + name, + enabled, + enabledInConfig, + enabledInLicense, + minimumLicenseRequired, + supportedFeatureIds, + isSystemActionType, + }) => ({ + id, + name, + enabled, + enabled_in_config: enabledInConfig, + enabled_in_license: enabledInLicense, + minimum_license_required: minimumLicenseRequired, + supported_feature_ids: supportedFeatureIds, + is_system_action_type: isSystemActionType, + }) + ); +}; diff --git a/x-pack/plugins/actions/server/routes/connector_types.ts b/x-pack/plugins/actions/server/routes/connector_types.ts deleted file mode 100644 index d54b35a7a99df..0000000000000 --- a/x-pack/plugins/actions/server/routes/connector_types.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 { IRouter } from '@kbn/core/server'; -import { schema } from '@kbn/config-schema'; -import { ILicenseState } from '../lib'; -import { ActionType, BASE_ACTION_API_PATH, RewriteResponseCase } from '../../common'; -import { ActionsRequestHandlerContext } from '../types'; -import { verifyAccessAndContext } from './verify_access_and_context'; - -const querySchema = schema.object({ - feature_id: schema.maybe(schema.string()), -}); - -const rewriteBodyRes: RewriteResponseCase = (results) => { - return results.map( - ({ - enabledInConfig, - enabledInLicense, - minimumLicenseRequired, - supportedFeatureIds, - isSystemActionType, - ...res - }) => ({ - ...res, - enabled_in_config: enabledInConfig, - enabled_in_license: enabledInLicense, - minimum_license_required: minimumLicenseRequired, - supported_feature_ids: supportedFeatureIds, - is_system_action_type: isSystemActionType, - }) - ); -}; - -export const connectorTypesRoute = ( - router: IRouter, - licenseState: ILicenseState -) => { - router.get( - { - path: `${BASE_ACTION_API_PATH}/connector_types`, - validate: { - query: querySchema, - }, - }, - router.handleLegacyErrors( - verifyAccessAndContext(licenseState, async function (context, req, res) { - const actionsClient = (await context.actions).getActionsClient(); - return res.ok({ - body: rewriteBodyRes(await actionsClient.listTypes({ featureId: req.query?.feature_id })), - }); - }) - ) - ); -}; diff --git a/x-pack/plugins/actions/server/routes/create.test.ts b/x-pack/plugins/actions/server/routes/create.test.ts index 2161e68e3706b..dd1317f57cd27 100644 --- a/x-pack/plugins/actions/server/routes/create.test.ts +++ b/x-pack/plugins/actions/server/routes/create.test.ts @@ -9,9 +9,9 @@ import { createActionRoute, bodySchema } from './create'; import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../lib/license_state.mock'; import { mockHandlerArguments } from './legacy/_mock_handler_arguments'; -import { actionsClientMock } from '../actions_client.mock'; import { verifyAccessAndContext } from './verify_access_and_context'; import { omit } from 'lodash'; +import { actionsClientMock } from '../actions_client/actions_client.mock'; jest.mock('./verify_access_and_context', () => ({ verifyAccessAndContext: jest.fn(), diff --git a/x-pack/plugins/actions/server/routes/execute.test.ts b/x-pack/plugins/actions/server/routes/execute.test.ts index 6bcab72fbc869..12960aeae47e6 100644 --- a/x-pack/plugins/actions/server/routes/execute.test.ts +++ b/x-pack/plugins/actions/server/routes/execute.test.ts @@ -10,7 +10,7 @@ import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../lib/license_state.mock'; import { mockHandlerArguments } from './legacy/_mock_handler_arguments'; import { asHttpRequestExecutionSource } from '../lib'; -import { actionsClientMock } from '../actions_client.mock'; +import { actionsClientMock } from '../actions_client/actions_client.mock'; import { ActionTypeExecutorResult } from '../types'; import { verifyAccessAndContext } from './verify_access_and_context'; diff --git a/x-pack/plugins/actions/server/routes/get.test.ts b/x-pack/plugins/actions/server/routes/get.test.ts index 76dda602945c9..a52cea1d49f6d 100644 --- a/x-pack/plugins/actions/server/routes/get.test.ts +++ b/x-pack/plugins/actions/server/routes/get.test.ts @@ -9,7 +9,7 @@ import { getActionRoute } from './get'; import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../lib/license_state.mock'; import { mockHandlerArguments } from './legacy/_mock_handler_arguments'; -import { actionsClientMock } from '../actions_client.mock'; +import { actionsClientMock } from '../actions_client/actions_client.mock'; import { verifyAccessAndContext } from './verify_access_and_context'; jest.mock('./verify_access_and_context', () => ({ diff --git a/x-pack/plugins/actions/server/routes/get_global_execution_kpi.test.ts b/x-pack/plugins/actions/server/routes/get_global_execution_kpi.test.ts index 838a1bf69789f..066d558bcfd59 100644 --- a/x-pack/plugins/actions/server/routes/get_global_execution_kpi.test.ts +++ b/x-pack/plugins/actions/server/routes/get_global_execution_kpi.test.ts @@ -8,7 +8,7 @@ import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../lib/license_state.mock'; import { mockHandlerArguments } from './legacy/_mock_handler_arguments'; -import { actionsClientMock } from '../actions_client.mock'; +import { actionsClientMock } from '../actions_client/actions_client.mock'; import { getGlobalExecutionKPIRoute } from './get_global_execution_kpi'; import { verifyAccessAndContext } from './verify_access_and_context'; diff --git a/x-pack/plugins/actions/server/routes/get_global_execution_logs.test.ts b/x-pack/plugins/actions/server/routes/get_global_execution_logs.test.ts index 1c309e14dae09..4654885a49bcb 100644 --- a/x-pack/plugins/actions/server/routes/get_global_execution_logs.test.ts +++ b/x-pack/plugins/actions/server/routes/get_global_execution_logs.test.ts @@ -9,7 +9,7 @@ import { getGlobalExecutionLogRoute } from './get_global_execution_logs'; import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../lib/license_state.mock'; import { mockHandlerArguments } from './legacy/_mock_handler_arguments'; -import { actionsClientMock } from '../actions_client.mock'; +import { actionsClientMock } from '../actions_client/actions_client.mock'; import { IExecutionLogResult } from '../../common'; import { verifyAccessAndContext } from './verify_access_and_context'; diff --git a/x-pack/plugins/actions/server/routes/get_oauth_access_token.test.ts b/x-pack/plugins/actions/server/routes/get_oauth_access_token.test.ts index ff13b021a209f..ae06068273ca3 100644 --- a/x-pack/plugins/actions/server/routes/get_oauth_access_token.test.ts +++ b/x-pack/plugins/actions/server/routes/get_oauth_access_token.test.ts @@ -11,7 +11,7 @@ import { licenseStateMock } from '../lib/license_state.mock'; import { mockHandlerArguments } from './legacy/_mock_handler_arguments'; import { verifyAccessAndContext } from './verify_access_and_context'; import { actionsConfigMock } from '../actions_config.mock'; -import { actionsClientMock } from '../actions_client.mock'; +import { actionsClientMock } from '../actions_client/actions_client.mock'; jest.mock('./verify_access_and_context', () => ({ verifyAccessAndContext: jest.fn(), diff --git a/x-pack/plugins/actions/server/routes/index.ts b/x-pack/plugins/actions/server/routes/index.ts index d46ce9dd5cc51..e5dce0ac3b6c7 100644 --- a/x-pack/plugins/actions/server/routes/index.ts +++ b/x-pack/plugins/actions/server/routes/index.ts @@ -8,13 +8,13 @@ import { IRouter } from '@kbn/core/server'; import { UsageCounter } from '@kbn/usage-collection-plugin/server'; import { getAllConnectorsRoute } from './connector/get_all'; +import { listTypesRoute } from './connector/list_types'; import { ILicenseState } from '../lib'; import { ActionsRequestHandlerContext } from '../types'; import { createActionRoute } from './create'; import { deleteActionRoute } from './delete'; import { executeActionRoute } from './execute'; import { getActionRoute } from './get'; -import { connectorTypesRoute } from './connector_types'; import { updateActionRoute } from './update'; import { getOAuthAccessToken } from './get_oauth_access_token'; import { defineLegacyRoutes } from './legacy'; @@ -39,7 +39,7 @@ export function defineRoutes(opts: RouteOptions) { getActionRoute(router, licenseState); getAllConnectorsRoute(router, licenseState); updateActionRoute(router, licenseState); - connectorTypesRoute(router, licenseState); + listTypesRoute(router, licenseState); executeActionRoute(router, licenseState); getGlobalExecutionLogRoute(router, licenseState); getGlobalExecutionKPIRoute(router, licenseState); diff --git a/x-pack/plugins/actions/server/routes/legacy/_mock_handler_arguments.ts b/x-pack/plugins/actions/server/routes/legacy/_mock_handler_arguments.ts index 07ac40b7e52e1..73906fa0a63e3 100644 --- a/x-pack/plugins/actions/server/routes/legacy/_mock_handler_arguments.ts +++ b/x-pack/plugins/actions/server/routes/legacy/_mock_handler_arguments.ts @@ -9,15 +9,16 @@ import { KibanaRequest, KibanaResponseFactory } from '@kbn/core/server'; import { identity } from 'lodash'; import type { MethodKeysOf } from '@kbn/utility-types'; import { httpServerMock } from '@kbn/core/server/mocks'; -import { ActionType } from '../../../common'; -import { ActionsClientMock, actionsClientMock } from '../../actions_client.mock'; import { ActionsRequestHandlerContext } from '../../types'; +import { actionsClientMock } from '../../mocks'; +import { ActionsClientMock } from '../../actions_client/actions_client.mock'; +import { ConnectorType } from '../../application/connector/types'; export function mockHandlerArguments( { actionsClient = actionsClientMock.create(), listTypes: listTypesRes = [], - }: { actionsClient?: ActionsClientMock; listTypes?: ActionType[] }, + }: { actionsClient?: ActionsClientMock; listTypes?: ConnectorType[] }, request: unknown, response?: Array> ): [ActionsRequestHandlerContext, KibanaRequest, KibanaResponseFactory] { diff --git a/x-pack/plugins/actions/server/routes/legacy/create.test.ts b/x-pack/plugins/actions/server/routes/legacy/create.test.ts index 0d285244342a6..e711f73265f53 100644 --- a/x-pack/plugins/actions/server/routes/legacy/create.test.ts +++ b/x-pack/plugins/actions/server/routes/legacy/create.test.ts @@ -9,7 +9,7 @@ import { createActionRoute } from './create'; import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../../lib/license_state.mock'; import { mockHandlerArguments } from './_mock_handler_arguments'; -import { actionsClientMock } from '../../actions_client.mock'; +import { actionsClientMock } from '../../actions_client/actions_client.mock'; import { verifyAccessAndContext } from '../verify_access_and_context'; import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; diff --git a/x-pack/plugins/actions/server/routes/legacy/execute.test.ts b/x-pack/plugins/actions/server/routes/legacy/execute.test.ts index 1f9e7bb7566da..53e7d038dfea5 100644 --- a/x-pack/plugins/actions/server/routes/legacy/execute.test.ts +++ b/x-pack/plugins/actions/server/routes/legacy/execute.test.ts @@ -10,7 +10,7 @@ import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../../lib/license_state.mock'; import { mockHandlerArguments } from './_mock_handler_arguments'; import { verifyApiAccess, ActionTypeDisabledError, asHttpRequestExecutionSource } from '../../lib'; -import { actionsClientMock } from '../../actions_client.mock'; +import { actionsClientMock } from '../../actions_client/actions_client.mock'; import { ActionTypeExecutorResult } from '../../types'; import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; diff --git a/x-pack/plugins/actions/server/routes/legacy/get.test.ts b/x-pack/plugins/actions/server/routes/legacy/get.test.ts index be5cc1c819e3a..6a19400da0fb5 100644 --- a/x-pack/plugins/actions/server/routes/legacy/get.test.ts +++ b/x-pack/plugins/actions/server/routes/legacy/get.test.ts @@ -10,7 +10,7 @@ import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../../lib/license_state.mock'; import { verifyApiAccess } from '../../lib'; import { mockHandlerArguments } from './_mock_handler_arguments'; -import { actionsClientMock } from '../../actions_client.mock'; +import { actionsClientMock } from '../../actions_client/actions_client.mock'; import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; diff --git a/x-pack/plugins/actions/server/routes/legacy/get_all.test.ts b/x-pack/plugins/actions/server/routes/legacy/get_all.test.ts index f7cdb56082a10..e999c769f3dbb 100644 --- a/x-pack/plugins/actions/server/routes/legacy/get_all.test.ts +++ b/x-pack/plugins/actions/server/routes/legacy/get_all.test.ts @@ -10,7 +10,7 @@ import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../../lib/license_state.mock'; import { verifyApiAccess } from '../../lib'; import { mockHandlerArguments } from './_mock_handler_arguments'; -import { actionsClientMock } from '../../actions_client.mock'; +import { actionsClientMock } from '../../actions_client/actions_client.mock'; import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; diff --git a/x-pack/plugins/actions/server/routes/legacy/update.test.ts b/x-pack/plugins/actions/server/routes/legacy/update.test.ts index 9158b4165a660..304b504636c91 100644 --- a/x-pack/plugins/actions/server/routes/legacy/update.test.ts +++ b/x-pack/plugins/actions/server/routes/legacy/update.test.ts @@ -10,7 +10,7 @@ import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../../lib/license_state.mock'; import { verifyApiAccess, ActionTypeDisabledError } from '../../lib'; import { mockHandlerArguments } from './_mock_handler_arguments'; -import { actionsClientMock } from '../../actions_client.mock'; +import { actionsClientMock } from '../../actions_client/actions_client.mock'; import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; diff --git a/x-pack/plugins/actions/server/routes/update.test.ts b/x-pack/plugins/actions/server/routes/update.test.ts index ac9f3dc45f660..aef179264ac48 100644 --- a/x-pack/plugins/actions/server/routes/update.test.ts +++ b/x-pack/plugins/actions/server/routes/update.test.ts @@ -9,7 +9,7 @@ import { bodySchema, updateActionRoute } from './update'; import { httpServiceMock } from '@kbn/core/server/mocks'; import { licenseStateMock } from '../lib/license_state.mock'; import { mockHandlerArguments } from './legacy/_mock_handler_arguments'; -import { actionsClientMock } from '../actions_client.mock'; +import { actionsClientMock } from '../actions_client/actions_client.mock'; import { verifyAccessAndContext } from './verify_access_and_context'; jest.mock('./verify_access_and_context', () => ({ diff --git a/x-pack/plugins/actions/server/routes/verify_access_and_context.test.ts b/x-pack/plugins/actions/server/routes/verify_access_and_context.test.ts index 4b07216172473..e079634fbfeff 100644 --- a/x-pack/plugins/actions/server/routes/verify_access_and_context.test.ts +++ b/x-pack/plugins/actions/server/routes/verify_access_and_context.test.ts @@ -8,7 +8,7 @@ import { licenseStateMock } from '../lib/license_state.mock'; import { verifyApiAccess, ActionTypeDisabledError } from '../lib'; import { mockHandlerArguments } from './legacy/_mock_handler_arguments'; -import { actionsClientMock } from '../actions_client.mock'; +import { actionsClientMock } from '../actions_client/actions_client.mock'; import { verifyAccessAndContext } from './verify_access_and_context'; jest.mock('../lib/verify_api_access', () => ({ diff --git a/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts b/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts index a4ad155092f25..3108ec9391cef 100644 --- a/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts +++ b/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts @@ -7,7 +7,7 @@ import { cloneDeep, get } from 'lodash'; import { useRef, useCallback, useMemo } from 'react'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/public'; +import { isCompleteResponse } from '@kbn/data-plugin/public'; import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { createRandomSamplerWrapper } from '@kbn/ml-random-sampler-utils'; @@ -110,8 +110,6 @@ export function useCategorizeRequest() { next: (result) => { if (isCompleteResponse(result)) { resolve(processCategoryResults(result, field, unwrap)); - } else if (isErrorResponse(result)) { - reject(result); } else { // partial results // Ignore partial results for now. diff --git a/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts b/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts index 0450905bde912..a44e176c1c073 100644 --- a/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts +++ b/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts @@ -6,11 +6,7 @@ */ import { useCallback, useRef, useState } from 'react'; -import { - type IKibanaSearchResponse, - isCompleteResponse, - isErrorResponse, -} from '@kbn/data-plugin/common'; +import { type IKibanaSearchResponse, isCompleteResponse } from '@kbn/data-plugin/common'; import { tap } from 'rxjs/operators'; import { useAiopsAppContext } from './use_aiops_app_context'; @@ -38,8 +34,6 @@ export function useCancellableSearch() { if (isCompleteResponse(result)) { setIsFetching(false); resolve(result); - } else if (isErrorResponse(result)) { - reject(result); } else { // partial results // Ignore partial results for now. diff --git a/x-pack/plugins/alerting/README.md b/x-pack/plugins/alerting/README.md index ba8a7ea8f763f..508a70874e37e 100644 --- a/x-pack/plugins/alerting/README.md +++ b/x-pack/plugins/alerting/README.md @@ -30,7 +30,7 @@ Table of Contents - [Internal HTTP APIs](#internal-http-apis) - [`GET /internal/alerting/rule/{id}/state`: Get rule state](#get-internalalertingruleidstate-get-rule-state) - [`GET /internal/alerting/rule/{id}/_alert_summary`: Get rule alert summary](#get-internalalertingruleidalertsummary-get-rule-alert-summary) - - [`POST /internal/alerting/rule/{id}/_update_api_key`: Update rule API key](#post-internalalertingruleidupdateapikey-update-rule-api-key) + - [`POST /api/alerting/rule/{id}/_update_api_key`: Update rule API key](#post-internalalertingruleidupdateapikey-update-rule-api-key) - [Alert Factory](#alert-factory) - [Templating Actions](#templating-actions) - [Examples](#examples) @@ -306,7 +306,7 @@ interface MyRuleTypeAlertContext extends AlertInstanceContext { } type MyRuleTypeActionGroups = 'default' | 'warning'; - + const myRuleType: RuleType< MyRuleTypeParams, MyRuleTypeExtractedParams, @@ -380,9 +380,9 @@ const myRuleType: RuleType< // Only execute if CPU usage is greater than threshold if (currentCpuUsage > threshold) { - // The first argument is a unique identifier for the alert. In this - // scenario the provided server will be used. Also, this ID will be - // used to make `getState()` return previous state, if any, on + // The first argument is a unique identifier for the alert. In this + // scenario the provided server will be used. Also, this ID will be + // used to make `getState()` return previous state, if any, on // matching identifiers. const alert = services.alertFactory.create(server); @@ -395,7 +395,7 @@ const myRuleType: RuleType< cpuUsage: currentCpuUsage, }); - // 'default' refers to the id of a group of actions to be scheduled + // 'default' refers to the id of a group of actions to be scheduled // for execution, see 'actions' in create rule section alert.scheduleActions('default', { server, @@ -406,8 +406,8 @@ const myRuleType: RuleType< // Returning updated rule type level state, this will become available // within the `state` function parameter at the next execution return { - // This is an example attribute you could set, it makes more sense - // to use this state when the rule type executes multiple + // This is an example attribute you could set, it makes more sense + // to use this state when the rule type executes multiple // alerts but wants a single place to track certain values. lastChecked: new Date(), }; @@ -497,7 +497,7 @@ features.registerKibanaFeature({ // grant `read` over our own type 'my-application-id.my-alert-type', // grant `read` over the built-in IndexThreshold - '.index-threshold', + '.index-threshold', // grant `read` over Uptime's TLS RuleType 'xpack.uptime.alerts.actionGroups.tls' ], @@ -507,7 +507,7 @@ features.registerKibanaFeature({ // grant `read` over our own type 'my-application-id.my-alert-type', // grant `read` over the built-in IndexThreshold - '.index-threshold', + '.index-threshold', // grant `read` over Uptime's TLS RuleType 'xpack.uptime.alerts.actionGroups.tls' ], @@ -555,7 +555,7 @@ features.registerKibanaFeature({ read: [ 'my-application-id.my-restricted-rule-type' ], - }, + }, alert: { all: [ 'my-application-id.my-rule-type' @@ -563,7 +563,7 @@ features.registerKibanaFeature({ read: [ 'my-application-id.my-restricted-rule-type' ], - }, + }, }, savedObject: { all: [], @@ -798,7 +798,7 @@ Query: |---|---|---| |dateStart|The date to start looking for alert events in the event log. Either an ISO date string, or a duration string indicating time since now.|string| -### `POST /internal/alerting/rule/{id}/_update_api_key`: Update rule API key +### `POST /api/alerting/rule/{id}/_update_api_key`: Update rule API key |Property|Description|Type| |---|---|---| diff --git a/x-pack/plugins/alerting/common/index.ts b/x-pack/plugins/alerting/common/index.ts index 3134ed5b69fdb..05b9e84ee2b7a 100644 --- a/x-pack/plugins/alerting/common/index.ts +++ b/x-pack/plugins/alerting/common/index.ts @@ -25,14 +25,6 @@ export type { RuleTaskState, RuleTaskParams, } from '@kbn/alerting-state-types'; -export { - rawAlertInstance, - DateFromString, - wrappedStateRt, - ActionsCompletion, - ruleStateSchema, - ruleParamsSchema, -} from '@kbn/alerting-state-types'; export * from './alert_summary'; export * from './builtin_action_groups'; export * from './bulk_edit'; diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.json b/x-pack/plugins/alerting/docs/openapi/bundled.json index 31b043f812d47..7a169c842a8e6 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.json +++ b/x-pack/plugins/alerting/docs/openapi/bundled.json @@ -12,18 +12,26 @@ "url": "https://www.elastic.co/licensing/elastic-license" } }, - "tags": [ - { - "name": "alerting", - "description": "Alerting APIs enable you to create and manage rules and alerts." - } - ], "servers": [ { "url": "http://localhost:5601", "description": "local" } ], + "security": [ + { + "basicAuth": [] + }, + { + "apiKeyAuth": [] + } + ], + "tags": [ + { + "name": "alerting", + "description": "Alerting APIs enable you to create and manage rules and alerts." + } + ], "paths": { "/s/{spaceId}/api/alerting/rule": { "post": { @@ -52,6 +60,9 @@ "createEsQueryRuleRequest": { "$ref": "#/components/examples/create_es_query_rule_request" }, + "createEsQueryKqlRuleRequest": { + "$ref": "#/components/examples/create_es_query_kql_rule_request" + }, "createIndexThresholdRuleRequest": { "$ref": "#/components/examples/create_index_threshold_rule_request" } @@ -71,6 +82,9 @@ "createEsQueryRuleResponse": { "$ref": "#/components/examples/create_es_query_rule_response" }, + "createEsQueryKqlRuleResponse": { + "$ref": "#/components/examples/create_es_query_kql_rule_response" + }, "createIndexThresholdRuleResponse": { "$ref": "#/components/examples/create_index_threshold_rule_response" } @@ -255,6 +269,9 @@ "createEsQueryRuleIdRequest": { "$ref": "#/components/examples/create_es_query_rule_request" }, + "createEsQueryKqlRuleIdRequest": { + "$ref": "#/components/examples/create_es_query_kql_rule_request" + }, "createIndexThreholdRuleIdRequest": { "$ref": "#/components/examples/create_index_threshold_rule_request" } @@ -274,6 +291,9 @@ "createEsQueryRuleIdResponse": { "$ref": "#/components/examples/create_es_query_rule_response" }, + "createEsQueryKqlRuleIdResponse": { + "$ref": "#/components/examples/create_es_query_kql_rule_response" + }, "createIndexThresholdRuleIdResponse": { "$ref": "#/components/examples/create_index_threshold_rule_response" } @@ -1188,6 +1208,52 @@ } ] }, + "/s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key": { + "post": { + "summary": "Updates the API key for a rule.", + "operationId": "updateRuleAPIKey", + "description": "The new API key has the credentials of the user that submits the request.", + "tags": [ + "alerting" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/rule_id" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call." + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, "/s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_mute": { "post": { "summary": "Mutes an alert.", @@ -6595,6 +6661,32 @@ } } }, + "400_response": { + "title": "Bad request", + "type": "object", + "required": [ + "error", + "message", + "statusCode" + ], + "properties": { + "error": { + "type": "string", + "enum": [ + "Bad Request" + ] + }, + "message": { + "type": "string" + }, + "statusCode": { + "type": "integer", + "enum": [ + 400 + ] + } + } + }, "alert_response_properties": { "title": "Legacy alert response properties", "type": "object", @@ -6710,10 +6802,62 @@ }, "examples": { "create_es_query_rule_request": { - "summary": "Create an Elasticsearch query rule.", + "summary": "Create an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL) to define its query and a server log connector to send notifications.", "value": { + "actions": [ + { + "group": "query matched", + "params": { + "level": "info", + "message": "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts." + }, + "id": "fdbece50-406c-11ee-850e-c71febc4ca7f", + "frequency": { + "throttle": "1d", + "summary": true, + "notify_when": "onThrottleInterval" + } + }, + { + "group": "recovered", + "params": { + "level": "info", + "message": "Recovered" + }, + "id": "fdbece50-406c-11ee-850e-c71febc4ca7f", + "frequency": { + "summary": false, + "notify_when": "onActionGroupChange" + } + } + ], "consumer": "alerts", "name": "my Elasticsearch query rule", + "params": { + "esQuery": "\"\"\"{\"query\":{\"match_all\" : {}}}\"\"\"", + "index": [ + "kibana_sample_data_logs" + ], + "size": 100, + "threshold": [ + 100 + ], + "thresholdComparator": ">", + "timeField": "@timestamp", + "timeWindowSize": 1, + "timeWindowUnit": "d" + }, + "rule_type_id": ".es-query", + "schedule": { + "interval": "1d" + } + } + }, + "create_es_query_kql_rule_request": { + "summary": "Create an Elasticsearch query rule that uses Kibana query language (KQL).", + "value": { + "consumer": "alerts", + "name": "my Elasticsearch query KQL rule", "params": { "aggType": "count", "excludeHitsFromPreviousRun": true, @@ -6786,11 +6930,92 @@ } }, "create_es_query_rule_response": { + "summary": "The create rule API returns a JSON object that contains details about the rule.", + "value": { + "id": "58148c70-407f-11ee-850e-c71febc4ca7f", + "enabled": true, + "name": "my Elasticsearch query rule", + "tags": [], + "rule_type_id": ".es-query", + "consumer": "alerts", + "schedule": { + "interval": "1d" + }, + "actions": [ + { + "group": "query matched", + "id": "fdbece50-406c-11ee-850e-c71febc4ca7f", + "params": { + "level": "info", + "message": "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts." + }, + "connector_type_id": ".server-log", + "frequency": { + "summary": true, + "notify_when": "onThrottleInterval", + "throttle": "1d" + }, + "uuid": "53f3c2a3-e5d0-4cfa-af3b-6f0881385e78" + }, + { + "group": "recovered", + "id": "fdbece50-406c-11ee-850e-c71febc4ca7f", + "params": { + "level": "info", + "message": "Recovered" + }, + "connector_type_id": ".server-log", + "frequency": { + "summary": false, + "notify_when": "onActionGroupChange", + "throttle": null + }, + "uuid": "2324e45b-c0df-45c7-9d70-4993e30be758" + } + ], + "params": { + "thresholdComparator": ">", + "timeWindowSize": 1, + "timeWindowUnit": "d", + "threshold": [ + 100 + ], + "size": 100, + "timeField": "@timestamp", + "index": [ + "kibana_sample_data_logs" + ], + "esQuery": "\"\"\"{\"query\":{\"match_all\" : {}}}\"\"\"", + "excludeHitsFromPreviousRun": true, + "aggType": "count", + "groupBy": "all", + "searchType": "esQuery" + }, + "scheduled_task_id": "58148c70-407f-11ee-850e-c71febc4ca7f", + "created_by": "elastic", + "updated_by": "elastic", + "created_at": "2023-08-22T00:03:38.263Z", + "updated_at": "2023-08-22T00:03:38.263Z", + "api_key_owner": "elastic", + "api_key_created_by_user": false, + "throttle": null, + "mute_all": false, + "notify_when": null, + "muted_alert_ids": [], + "execution_status": { + "status": "pending", + "last_execution_date": "2023-08-22T00:03:38.263Z" + }, + "revision": 0, + "running": false + } + }, + "create_es_query_kql_rule_response": { "summary": "The create rule API returns a JSON object that contains details about the rule.", "value": { "id": "7bd506d0-2284-11ee-8fad-6101956ced88", "enabled": true, - "name": "my Elasticsearch query rule\"", + "name": "my Elasticsearch query KQL rule\"", "tags": [], "rule_type_id": ".es-query", "consumer": "alerts", @@ -7504,13 +7729,5 @@ ] } } - }, - "security": [ - { - "basicAuth": [] - }, - { - "apiKeyAuth": [] - } - ] + } } \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.yaml b/x-pack/plugins/alerting/docs/openapi/bundled.yaml index 72c8cf2da3828..0465a9218f2db 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.yaml +++ b/x-pack/plugins/alerting/docs/openapi/bundled.yaml @@ -8,12 +8,15 @@ info: license: name: Elastic License 2.0 url: https://www.elastic.co/licensing/elastic-license -tags: - - name: alerting - description: Alerting APIs enable you to create and manage rules and alerts. servers: - url: http://localhost:5601 description: local +security: + - basicAuth: [] + - apiKeyAuth: [] +tags: + - name: alerting + description: Alerting APIs enable you to create and manage rules and alerts. paths: /s/{spaceId}/api/alerting/rule: post: @@ -35,6 +38,8 @@ paths: examples: createEsQueryRuleRequest: $ref: '#/components/examples/create_es_query_rule_request' + createEsQueryKqlRuleRequest: + $ref: '#/components/examples/create_es_query_kql_rule_request' createIndexThresholdRuleRequest: $ref: '#/components/examples/create_index_threshold_rule_request' responses: @@ -47,6 +52,8 @@ paths: examples: createEsQueryRuleResponse: $ref: '#/components/examples/create_es_query_rule_response' + createEsQueryKqlRuleResponse: + $ref: '#/components/examples/create_es_query_kql_rule_response' createIndexThresholdRuleResponse: $ref: '#/components/examples/create_index_threshold_rule_response' '401': @@ -155,6 +162,8 @@ paths: examples: createEsQueryRuleIdRequest: $ref: '#/components/examples/create_es_query_rule_request' + createEsQueryKqlRuleIdRequest: + $ref: '#/components/examples/create_es_query_kql_rule_request' createIndexThreholdRuleIdRequest: $ref: '#/components/examples/create_index_threshold_rule_request' responses: @@ -167,6 +176,8 @@ paths: examples: createEsQueryRuleIdResponse: $ref: '#/components/examples/create_es_query_rule_response' + createEsQueryKqlRuleIdResponse: + $ref: '#/components/examples/create_es_query_kql_rule_response' createIndexThresholdRuleIdResponse: $ref: '#/components/examples/create_index_threshold_rule_response' '401': @@ -732,6 +743,30 @@ paths: - url: https://localhost:5601 servers: - url: https://localhost:5601 + /s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key: + post: + summary: Updates the API key for a rule. + operationId: updateRuleAPIKey + description: The new API key has the credentials of the user that submits the request. + tags: + - alerting + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/rule_id' + - $ref: '#/components/parameters/space_id' + responses: + '200': + description: Indicates a successful call. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 /s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_mute: post: summary: Mutes an alert. @@ -4503,6 +4538,24 @@ components: $ref: '#/components/schemas/tags' throttle: $ref: '#/components/schemas/throttle' + 400_response: + title: Bad request + type: object + required: + - error + - message + - statusCode + properties: + error: + type: string + enum: + - Bad Request + message: + type: string + statusCode: + type: integer + enum: + - 400 alert_response_properties: title: Legacy alert response properties type: object @@ -4588,10 +4641,47 @@ components: example: elastic examples: create_es_query_rule_request: - summary: Create an Elasticsearch query rule. + summary: Create an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL) to define its query and a server log connector to send notifications. value: + actions: + - group: query matched + params: + level: info + message: The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts. + id: fdbece50-406c-11ee-850e-c71febc4ca7f + frequency: + throttle: 1d + summary: true + notify_when: onThrottleInterval + - group: recovered + params: + level: info + message: Recovered + id: fdbece50-406c-11ee-850e-c71febc4ca7f + frequency: + summary: false + notify_when: onActionGroupChange consumer: alerts name: my Elasticsearch query rule + params: + esQuery: '"""{"query":{"match_all" : {}}}"""' + index: + - kibana_sample_data_logs + size: 100 + threshold: + - 100 + thresholdComparator: '>' + timeField: '@timestamp' + timeWindowSize: 1 + timeWindowUnit: d + rule_type_id: .es-query + schedule: + interval: 1d + create_es_query_kql_rule_request: + summary: Create an Elasticsearch query rule that uses Kibana query language (KQL). + value: + consumer: alerts + name: my Elasticsearch query KQL rule params: aggType: count excludeHitsFromPreviousRun: true @@ -4650,11 +4740,76 @@ components: tags: - cpu create_es_query_rule_response: + summary: The create rule API returns a JSON object that contains details about the rule. + value: + id: 58148c70-407f-11ee-850e-c71febc4ca7f + enabled: true + name: my Elasticsearch query rule + tags: [] + rule_type_id: .es-query + consumer: alerts + schedule: + interval: 1d + actions: + - group: query matched + id: fdbece50-406c-11ee-850e-c71febc4ca7f + params: + level: info + message: The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts. + connector_type_id: .server-log + frequency: + summary: true + notify_when: onThrottleInterval + throttle: 1d + uuid: 53f3c2a3-e5d0-4cfa-af3b-6f0881385e78 + - group: recovered + id: fdbece50-406c-11ee-850e-c71febc4ca7f + params: + level: info + message: Recovered + connector_type_id: .server-log + frequency: + summary: false + notify_when: onActionGroupChange + throttle: null + uuid: 2324e45b-c0df-45c7-9d70-4993e30be758 + params: + thresholdComparator: '>' + timeWindowSize: 1 + timeWindowUnit: d + threshold: + - 100 + size: 100 + timeField: '@timestamp' + index: + - kibana_sample_data_logs + esQuery: '"""{"query":{"match_all" : {}}}"""' + excludeHitsFromPreviousRun: true + aggType: count + groupBy: all + searchType: esQuery + scheduled_task_id: 58148c70-407f-11ee-850e-c71febc4ca7f + created_by: elastic + updated_by: elastic + created_at: '2023-08-22T00:03:38.263Z' + updated_at: '2023-08-22T00:03:38.263Z' + api_key_owner: elastic + api_key_created_by_user: false + throttle: null + mute_all: false + notify_when: null + muted_alert_ids: [] + execution_status: + status: pending + last_execution_date: '2023-08-22T00:03:38.263Z' + revision: 0 + running: false + create_es_query_kql_rule_response: summary: The create rule API returns a JSON object that contains details about the rule. value: id: 7bd506d0-2284-11ee-8fad-6101956ced88 enabled: true - name: my Elasticsearch query rule" + name: my Elasticsearch query KQL rule" tags: [] rule_type_id: .es-query consumer: alerts @@ -5217,6 +5372,3 @@ components: id: recovered name: Recovered rule_task_timeout: 5m -security: - - basicAuth: [] - - apiKeyAuth: [] diff --git a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_request.yaml b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_request.yaml new file mode 100644 index 0000000000000..e505fd8964463 --- /dev/null +++ b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_request.yaml @@ -0,0 +1,23 @@ +summary: Create an Elasticsearch query rule that uses Kibana query language (KQL). +value: + consumer: alerts + name: my Elasticsearch query KQL rule + params: + aggType: count + excludeHitsFromPreviousRun: true + groupBy: all + searchConfiguration: + query: + query: '""geo.src : "US" ""' + language: kuery + index: 90943e30-9a47-11e8-b64d-95841ca0b247 + searchType: searchSource + size: 100 + threshold: + - 1000 + thresholdComparator: ">" + timeWindowSize: 5 + timeWindowUnit: m + rule_type_id: .es-query + schedule: + interval: 1m diff --git a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_response.yaml b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_response.yaml new file mode 100644 index 0000000000000..0a30c4e6dd41e --- /dev/null +++ b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_kql_rule_response.yaml @@ -0,0 +1,43 @@ +summary: The create rule API returns a JSON object that contains details about the rule. +value: + id: 7bd506d0-2284-11ee-8fad-6101956ced88 + enabled: true + name: my Elasticsearch query KQL rule" + tags: [] + rule_type_id: .es-query + consumer: alerts + schedule: + interval: 1m + actions: [] + params: + searchConfiguration: + query: + query: '""geo.src : "US" ""' + language: kuery + index: 90943e30-9a47-11e8-b64d-95841ca0b247 + searchType: searchSource + timeWindowSize: 5 + timeWindowUnit: m + threshold: + - 1000 + thresholdComparator: ">" + size: 100 + aggType: count + groupBy: all + excludeHitsFromPreviousRun: true + created_by: elastic + updated_by: elastic + created_at: '2023-07-14T20:24:50.729Z' + updated_at: '2023-07-14T20:24:50.729Z' + api_key_owner: elastic + api_key_created_by_user: false + throttle: null + notify_when: null + mute_all: false + muted_alert_ids: [] + scheduled_task_id: 7bd506d0-2284-11ee-8fad-6101956ced88 + execution_status: + status: pending + last_execution_date: '2023-07-14T20:24:50.729Z' + revision: 0 + running: false \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_request.yaml b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_request.yaml index b17f6626b34dc..bff7a8f0bd8f6 100644 --- a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_request.yaml +++ b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_request.yaml @@ -1,23 +1,36 @@ -summary: Create an Elasticsearch query rule. +summary: Create an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL) to define its query and a server log connector to send notifications. value: + actions: + - group: query matched + params: + level: info + message: "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts." + id: fdbece50-406c-11ee-850e-c71febc4ca7f + frequency: + throttle: "1d" + summary: true + notify_when: onThrottleInterval + - group: recovered + params: + level: info + message: Recovered + id: fdbece50-406c-11ee-850e-c71febc4ca7f + frequency: + summary: false + notify_when: onActionGroupChange consumer: alerts name: my Elasticsearch query rule - params: - aggType: count - excludeHitsFromPreviousRun: true - groupBy: all - searchConfiguration: - query: - query: '""geo.src : "US" ""' - language: kuery - index: 90943e30-9a47-11e8-b64d-95841ca0b247 - searchType: searchSource + params: + esQuery: '"""{"query":{"match_all" : {}}}"""' + index: + - kibana_sample_data_logs size: 100 threshold: - - 1000 + - 100 thresholdComparator: ">" - timeWindowSize: 5 - timeWindowUnit: m + timeField: "@timestamp" + timeWindowSize: 1 + timeWindowUnit: d rule_type_id: .es-query schedule: - interval: 1m + interval: 1d \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_response.yaml b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_response.yaml index 5f24e00421a6f..9601843a42e3b 100644 --- a/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_response.yaml +++ b/x-pack/plugins/alerting/docs/openapi/components/examples/create_es_query_rule_response.yaml @@ -1,43 +1,64 @@ summary: The create rule API returns a JSON object that contains details about the rule. value: - id: 7bd506d0-2284-11ee-8fad-6101956ced88 + id: 58148c70-407f-11ee-850e-c71febc4ca7f enabled: true - name: my Elasticsearch query rule" + name: my Elasticsearch query rule tags: [] rule_type_id: .es-query consumer: alerts - schedule: - interval: 1m - actions: [] - params: - searchConfiguration: - query: - query: '""geo.src : "US" ""' - language: kuery - index: 90943e30-9a47-11e8-b64d-95841ca0b247 - searchType: searchSource - timeWindowSize: 5 - timeWindowUnit: m - threshold: - - 1000 + schedule: + interval: 1d + actions: + - group: query matched + id: fdbece50-406c-11ee-850e-c71febc4ca7f + params: + level: info + message: "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts." + connector_type_id: .server-log + frequency: + summary: true + notify_when: onThrottleInterval + throttle: "1d" + uuid: 53f3c2a3-e5d0-4cfa-af3b-6f0881385e78 + - group: recovered + id: fdbece50-406c-11ee-850e-c71febc4ca7f + params: + level: info + message: Recovered + connector_type_id: .server-log + frequency: + summary: false + notify_when: onActionGroupChange + throttle: null + uuid: 2324e45b-c0df-45c7-9d70-4993e30be758 + params: thresholdComparator: ">" + timeWindowSize: 1 + timeWindowUnit: d + threshold: + - 100 size: 100 + timeField: "@timestamp" + index: + - kibana_sample_data_logs + esQuery: '"""{"query":{"match_all" : {}}}"""' + excludeHitsFromPreviousRun: true aggType: count groupBy: all - excludeHitsFromPreviousRun: true + searchType: esQuery + scheduled_task_id: 58148c70-407f-11ee-850e-c71febc4ca7f created_by: elastic updated_by: elastic - created_at: '2023-07-14T20:24:50.729Z' - updated_at: '2023-07-14T20:24:50.729Z' + created_at: '2023-08-22T00:03:38.263Z' + updated_at: '2023-08-22T00:03:38.263Z' api_key_owner: elastic api_key_created_by_user: false throttle: null - notify_when: null mute_all: false + notify_when: null muted_alert_ids: [] - scheduled_task_id: 7bd506d0-2284-11ee-8fad-6101956ced88 execution_status: status: pending - last_execution_date: '2023-07-14T20:24:50.729Z' + last_execution_date: '2023-08-22T00:03:38.263Z' revision: 0 running: false \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/components/schemas/400_response.yaml b/x-pack/plugins/alerting/docs/openapi/components/schemas/400_response.yaml new file mode 100644 index 0000000000000..ab0887586c0eb --- /dev/null +++ b/x-pack/plugins/alerting/docs/openapi/components/schemas/400_response.yaml @@ -0,0 +1,17 @@ +title: Bad request +type: object +required: + - error + - message + - statusCode +properties: + error: + type: string + enum: + - Bad Request + message: + type: string + statusCode: + type: integer + enum: + - 400 \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml b/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml index 5e73a74c058a0..f6beba7fdb82c 100644 --- a/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml +++ b/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml @@ -33,6 +33,8 @@ paths: $ref: 'paths/s@{spaceid}@api@alerting@rule@{ruleid}@_mute_all.yaml' '/s/{spaceId}/api/alerting/rule/{ruleId}/_unmute_all': $ref: 'paths/s@{spaceid}@api@alerting@rule@{ruleid}@_unmute_all.yaml' + '/s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key': + $ref: 'paths/s@{spaceid}@api@alerting@rule@{ruleid}@_update_api_key.yaml' '/s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_mute': $ref: 'paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_mute.yaml' '/s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_unmute': diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule.yaml index 5a7ebd986a234..f88f69a437a9c 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule.yaml @@ -23,6 +23,8 @@ post: examples: createEsQueryRuleRequest: $ref: '../components/examples/create_es_query_rule_request.yaml' + createEsQueryKqlRuleRequest: + $ref: '../components/examples/create_es_query_kql_rule_request.yaml' createIndexThresholdRuleRequest: $ref: '../components/examples/create_index_threshold_rule_request.yaml' responses: @@ -35,6 +37,8 @@ post: examples: createEsQueryRuleResponse: $ref: '../components/examples/create_es_query_rule_response.yaml' + createEsQueryKqlRuleResponse: + $ref: '../components/examples/create_es_query_kql_rule_response.yaml' createIndexThresholdRuleResponse: $ref: '../components/examples/create_index_threshold_rule_response.yaml' '401': diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}.yaml index 9bfd620d9bfd5..058e825f1aac3 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}.yaml @@ -104,6 +104,8 @@ post: examples: createEsQueryRuleIdRequest: $ref: '../components/examples/create_es_query_rule_request.yaml' + createEsQueryKqlRuleIdRequest: + $ref: '../components/examples/create_es_query_kql_rule_request.yaml' createIndexThreholdRuleIdRequest: $ref: '../components/examples/create_index_threshold_rule_request.yaml' responses: @@ -116,6 +118,8 @@ post: examples: createEsQueryRuleIdResponse: $ref: '../components/examples/create_es_query_rule_response.yaml' + createEsQueryKqlRuleIdResponse: + $ref: '../components/examples/create_es_query_kql_rule_response.yaml' createIndexThresholdRuleIdResponse: $ref: '../components/examples/create_index_threshold_rule_response.yaml' '401': diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_update_api_key.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_update_api_key.yaml new file mode 100644 index 0000000000000..a4d79f12943cc --- /dev/null +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_update_api_key.yaml @@ -0,0 +1,23 @@ +post: + summary: Updates the API key for a rule. + operationId: updateRuleAPIKey + description: The new API key has the credentials of the user that submits the request. + tags: + - alerting + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + - $ref: '../components/parameters/rule_id.yaml' + - $ref: '../components/parameters/space_id.yaml' + responses: + '200': + description: Indicates a successful call. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/x-pack/plugins/alerting/kibana.jsonc b/x-pack/plugins/alerting/kibana.jsonc index 86dc1a393085e..f37b7c7d72676 100644 --- a/x-pack/plugins/alerting/kibana.jsonc +++ b/x-pack/plugins/alerting/kibana.jsonc @@ -30,7 +30,8 @@ "usageCollection", "security", "monitoringCollection", - "spaces" + "spaces", + "serverless", ], "extraPublicDirs": [ "common", diff --git a/x-pack/plugins/alerting/server/alert/alert.test.ts b/x-pack/plugins/alerting/server/alert/alert.test.ts index 95894fe440107..c4db2189e6d26 100644 --- a/x-pack/plugins/alerting/server/alert/alert.test.ts +++ b/x-pack/plugins/alerting/server/alert/alert.test.ts @@ -44,7 +44,7 @@ describe('isThrottled', () => { const alert = new Alert('1', { meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -58,10 +58,10 @@ describe('isThrottled', () => { const alert = new Alert('1', { meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', actions: { - 'slack:alert:1h': { date: new Date() }, + 'slack:alert:1h': { date: new Date().toISOString() }, }, }, }, @@ -77,7 +77,7 @@ describe('isThrottled', () => { const alert = new Alert('1', { meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -91,7 +91,7 @@ describe('isThrottled', () => { const alert = new Alert('1', { meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -105,10 +105,10 @@ describe('isThrottled', () => { const alert = new Alert('1', { meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', actions: { - '111-111': { date: new Date() }, + '111-111': { date: new Date().toISOString() }, }, }, }, @@ -122,10 +122,10 @@ describe('isThrottled', () => { const alert = new Alert('1', { meta: { lastScheduledActions: { - date: new Date('2020-01-01'), + date: new Date('2020-01-01').toISOString(), group: 'default', actions: { - '111-111': { date: new Date() }, + '111-111': { date: new Date().toISOString() }, }, }, }, @@ -141,10 +141,10 @@ describe('isThrottled', () => { const alert = new Alert('1', { meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', actions: { - '111-111': { date: new Date() }, + '111-111': { date: new Date().toISOString() }, }, }, }, @@ -165,7 +165,7 @@ describe('scheduledActionGroupHasChanged()', () => { const alert = new Alert('1', { meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -184,7 +184,7 @@ describe('scheduledActionGroupHasChanged()', () => { const alert = new Alert('1', { meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -274,7 +274,7 @@ describe('scheduleActions()', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -288,7 +288,7 @@ describe('scheduleActions()', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -302,7 +302,7 @@ describe('scheduleActions()', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -396,10 +396,10 @@ describe('updateLastScheduledActions()', () => { flappingHistory: [], maintenanceWindowIds: [], lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', actions: { - 'slack:alert:1h': { date: new Date() }, + 'slack:alert:1h': { date: new Date().toISOString() }, }, }, }, @@ -429,7 +429,7 @@ describe('getContext()', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -442,7 +442,7 @@ describe('getContext()', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -458,7 +458,7 @@ describe('hasContext()', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -472,7 +472,7 @@ describe('hasContext()', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -486,7 +486,7 @@ describe('hasContext()', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, }, @@ -503,7 +503,7 @@ describe('toJSON', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, flappingHistory: [false, true], @@ -520,7 +520,7 @@ describe('toJSON', () => { }, meta: { lastScheduledActions: { - date: expect.any(Date), + date: expect.any(String), group: 'default', }, uuid: expect.any(String), @@ -538,7 +538,7 @@ describe('toRaw', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, flappingHistory: [false, true, true], @@ -557,7 +557,7 @@ describe('toRaw', () => { state: { foo: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'default', }, flappingHistory: [false, true, true], diff --git a/x-pack/plugins/alerting/server/alert/alert.ts b/x-pack/plugins/alerting/server/alert/alert.ts index 4e08a314bb3a4..b05c3bea22cc3 100644 --- a/x-pack/plugins/alerting/server/alert/alert.ts +++ b/x-pack/plugins/alerting/server/alert/alert.ts @@ -7,12 +7,12 @@ import { v4 as uuidV4 } from 'uuid'; import { isEmpty } from 'lodash'; +import { MutableAlertInstanceMeta } from '@kbn/alerting-state-types'; import { AlertHit, CombinedSummarizedAlerts } from '../types'; import { AlertInstanceMeta, AlertInstanceState, RawAlertInstance, - rawAlertInstance, AlertInstanceContext, DefaultActionGroupId, LastScheduledActions, @@ -52,7 +52,7 @@ export class Alert< ActionGroupIds extends string = never > { private scheduledExecutionOptions?: ScheduledExecutionOptions; - private meta: AlertInstanceMeta; + private meta: MutableAlertInstanceMeta; private state: State; private context: Context; private readonly id: string; @@ -111,11 +111,13 @@ export class Alert< this.meta.lastScheduledActions.actions[uuid] || this.meta.lastScheduledActions.actions[actionHash]; // actionHash must be removed once all the hash identifiers removed from the task state const lastTriggerDate = actionInState?.date; - return !!(lastTriggerDate && lastTriggerDate.getTime() + throttleMills > Date.now()); + return !!( + lastTriggerDate && new Date(lastTriggerDate).getTime() + throttleMills > Date.now() + ); } return false; } else { - return this.meta.lastScheduledActions.date.getTime() + throttleMills > Date.now(); + return new Date(this.meta.lastScheduledActions.date).getTime() + throttleMills > Date.now(); } } return false; @@ -202,7 +204,7 @@ export class Alert< if (!this.meta.lastScheduledActions) { this.meta.lastScheduledActions = {} as LastScheduledActions; } - const date = new Date(); + const date = new Date().toISOString(); this.meta.lastScheduledActions.group = group; this.meta.lastScheduledActions.date = date; @@ -224,7 +226,7 @@ export class Alert< * Used to serialize alert instance state */ toJSON() { - return rawAlertInstance.encode(this.toRaw()); + return this.toRaw(); } toRaw(recovered: boolean = false): RawAlertInstance { diff --git a/x-pack/plugins/alerting/server/alert/create_alert_factory.test.ts b/x-pack/plugins/alerting/server/alert/create_alert_factory.test.ts index dc9c09269403a..c991ed961a89c 100644 --- a/x-pack/plugins/alerting/server/alert/create_alert_factory.test.ts +++ b/x-pack/plugins/alerting/server/alert/create_alert_factory.test.ts @@ -49,7 +49,10 @@ describe('createAlertFactory()', () => { test('reuses existing alerts', () => { const alert = new Alert('1', { state: { foo: true }, - meta: { lastScheduledActions: { group: 'default', date: new Date() }, uuid: 'uuid-previous' }, + meta: { + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'uuid-previous', + }, }); const alertFactory = createAlertFactory({ alerts: { @@ -65,7 +68,7 @@ describe('createAlertFactory()', () => { uuid: 'uuid-previous', flappingHistory: [], lastScheduledActions: { - date: expect.any(Date), + date: expect.any(String), group: 'default', }, }, @@ -100,7 +103,10 @@ describe('createAlertFactory()', () => { test('gets alert if it exists, returns null if it does not', () => { const alert = new Alert('1', { state: { foo: true }, - meta: { lastScheduledActions: { group: 'default', date: new Date() }, uuid: 'uuid-previous' }, + meta: { + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'uuid-previous', + }, }); const alertFactory = createAlertFactory({ alerts: { diff --git a/x-pack/plugins/alerting/server/alerts_client/alerts_client.test.ts b/x-pack/plugins/alerting/server/alerts_client/alerts_client.test.ts index 06b90dd675b48..78b2e41431c22 100644 --- a/x-pack/plugins/alerting/server/alerts_client/alerts_client.test.ts +++ b/x-pack/plugins/alerting/server/alerts_client/alerts_client.test.ts @@ -14,6 +14,7 @@ import { RuleNotifyWhen, } from '../types'; import * as LegacyAlertsClientModule from './legacy_alerts_client'; +import { LegacyAlertsClient } from './legacy_alerts_client'; import { Alert } from '../alert/alert'; import { AlertsClient, AlertsClientParams } from './alerts_client'; import { GetSummarizedAlertsParams, ProcessAndLogAlertsOpts } from './types'; @@ -30,6 +31,7 @@ import { getParamsByTimeQuery, mockAAD, } from './alerts_client_fixtures'; +import { getDataStreamAdapter } from '../alerts_service/lib/data_stream_adapter'; const date = '2023-03-28T22:27:28.159Z'; const maxAlerts = 1000; @@ -81,406 +83,310 @@ const mockSetContext = jest.fn(); describe('Alerts Client', () => { let alertsClientParams: AlertsClientParams; let processAndLogAlertsOpts: ProcessAndLogAlertsOpts; + beforeAll(() => { jest.useFakeTimers(); jest.setSystemTime(new Date(date)); }); - beforeEach(() => { - jest.clearAllMocks(); - logger = loggingSystemMock.createLogger(); - alertsClientParams = { - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - ruleType, - namespace: 'default', - rule: alertRuleData, - kibanaVersion: '8.9.0', - }; - processAndLogAlertsOpts = { - eventLogger: alertingEventLogger, - ruleRunMetricsStore, - shouldLogAlerts: false, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - notifyWhen: RuleNotifyWhen.CHANGE, - maintenanceWindowIds: [], - }; - }); - afterAll(() => { jest.useRealTimers(); }); - describe('initializeExecution()', () => { - test('should initialize LegacyAlertsClient', async () => { - mockLegacyAlertsClient.getTrackedAlerts.mockImplementation(() => ({ - active: {}, - recovered: {}, - })); - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - - const alertsClient = new AlertsClient(alertsClientParams); - - const opts = { - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }; - await alertsClient.initializeExecution(opts); - expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); - - // no alerts to query for - expect(clusterClient.search).not.toHaveBeenCalled(); - - spy.mockRestore(); - }); - - test('should skip track alerts ruleType shouldWrite is false', async () => { - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - - const alertsClient = new AlertsClient({ - ...alertsClientParams, - ruleType: { - ...alertsClientParams.ruleType, - alerts: { - context: 'test', - mappings: { fieldMap: { field: { type: 'keyword', required: false } } }, - shouldWrite: false, - }, - }, - }); - - const opts = { - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }; - await alertsClient.initializeExecution(opts); - expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); - expect(mockLegacyAlertsClient.getTrackedAlerts).not.toHaveBeenCalled(); - spy.mockRestore(); - }); + for (const useDataStreamForAlerts of [false, true]) { + const label = useDataStreamForAlerts ? 'data streams' : 'aliases'; - test('should query for alert UUIDs if they exist', async () => { - mockLegacyAlertsClient.getTrackedAlerts.mockImplementation(() => ({ - active: { - '1': new Alert('1', { - state: { foo: true }, - meta: { - flapping: false, - flappingHistory: [true, false], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'abc', - }, - }), - '2': new Alert('2', { - state: { foo: false }, - meta: { - flapping: false, - flappingHistory: [true, false, false], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'def', - }, - }), - }, - recovered: { - '3': new Alert('3', { - state: { foo: false }, - meta: { - flapping: false, - flappingHistory: [true, false, false], - uuid: 'xyz', - }, - }), - }, - })); - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - - const alertsClient = new AlertsClient(alertsClientParams); - - const opts = { - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }; - await alertsClient.initializeExecution(opts); - expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); - - expect(clusterClient.search).toHaveBeenCalledWith({ - body: { - query: { - bool: { - filter: [ - { term: { 'kibana.alert.rule.uuid': '1' } }, - { terms: { 'kibana.alert.uuid': ['abc', 'def', 'xyz'] } }, - ], - }, - }, - size: 3, - }, - index: '.internal.alerts-test.alerts-default-*', - }); + describe(`using ${label} for alert indices`, () => { + beforeEach(() => { + jest.clearAllMocks(); + logger = loggingSystemMock.createLogger(); + alertsClientParams = { + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + ruleType, + namespace: 'default', + rule: alertRuleData, + kibanaVersion: '8.9.0', + dataStreamAdapter: getDataStreamAdapter({ useDataStreamForAlerts }), + }; + processAndLogAlertsOpts = { + eventLogger: alertingEventLogger, + ruleRunMetricsStore, + shouldLogAlerts: false, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + notifyWhen: RuleNotifyWhen.CHANGE, + maintenanceWindowIds: [], + }; + }); + + describe('initializeExecution()', () => { + test('should initialize LegacyAlertsClient', async () => { + mockLegacyAlertsClient.getTrackedAlerts.mockImplementation(() => ({ + active: {}, + recovered: {}, + })); + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + + const alertsClient = new AlertsClient(alertsClientParams); + + const opts = { + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }; + await alertsClient.initializeExecution(opts); + expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); + + // no alerts to query for + expect(clusterClient.search).not.toHaveBeenCalled(); + + spy.mockRestore(); + }); - spy.mockRestore(); - }); + test('should skip track alerts ruleType shouldWrite is false', async () => { + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); - test('should split queries into chunks when there are greater than 10,000 alert UUIDs', async () => { - mockLegacyAlertsClient.getTrackedAlerts.mockImplementation(() => ({ - active: range(15000).reduce((acc: Record>, value: number) => { - const id: string = `${value}`; - acc[id] = new Alert(id, { - state: { foo: true }, - meta: { - flapping: false, - flappingHistory: [true, false], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: id, + const alertsClient = new AlertsClient({ + ...alertsClientParams, + ruleType: { + ...alertsClientParams.ruleType, + alerts: { + context: 'test', + mappings: { fieldMap: { field: { type: 'keyword', required: false } } }, + shouldWrite: false, + }, }, }); - return acc; - }, {}), - recovered: {}, - })); - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - - const alertsClient = new AlertsClient(alertsClientParams); - - const opts = { - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }; - await alertsClient.initializeExecution(opts); - expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); - - expect(clusterClient.search).toHaveBeenCalledTimes(2); - - spy.mockRestore(); - }); - - test('should log but not throw if query returns error', async () => { - clusterClient.search.mockImplementation(() => { - throw new Error('search failed!'); - }); - mockLegacyAlertsClient.getTrackedAlerts.mockImplementation(() => ({ - active: { - '1': new Alert('1', { - state: { foo: true }, - meta: { - flapping: false, - flappingHistory: [true, false], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'abc', - }, - }), - }, - recovered: {}, - })); - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - - const alertsClient = new AlertsClient(alertsClientParams); - - const opts = { - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }; - await alertsClient.initializeExecution(opts); - expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); - - expect(clusterClient.search).toHaveBeenCalledWith({ - body: { - query: { - bool: { - filter: [ - { term: { 'kibana.alert.rule.uuid': '1' } }, - { terms: { 'kibana.alert.uuid': ['abc'] } }, - ], - }, - }, - size: 1, - }, - index: '.internal.alerts-test.alerts-default-*', - }); - - expect(logger.error).toHaveBeenCalledWith( - `Error searching for tracked alerts by UUID - search failed!` - ); - - spy.mockRestore(); - }); - }); - - describe('persistAlerts()', () => { - test('should index new alerts', async () => { - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); - // Report 2 new alerts - const alertExecutorService = alertsClient.factory(); - alertExecutorService.create('1').scheduleActions('default'); - alertExecutorService.create('2').scheduleActions('default'); - - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); - - await alertsClient.persistAlerts(); - - const { alertsToReturn } = alertsClient.getAlertsToSerialize(); - const uuid1 = alertsToReturn['1'].meta?.uuid; - const uuid2 = alertsToReturn['2'].meta?.uuid; + const opts = { + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }; + await alertsClient.initializeExecution(opts); + expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); + expect(mockLegacyAlertsClient.getTrackedAlerts).not.toHaveBeenCalled(); + spy.mockRestore(); + }); - expect(clusterClient.bulk).toHaveBeenCalledWith({ - index: '.alerts-test.alerts-default', - refresh: 'wait_for', - require_alias: true, - body: [ - { index: { _id: uuid1 } }, - // new alert doc - { - '@timestamp': date, - event: { - action: 'open', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', + test('should query for alert UUIDs if they exist', async () => { + mockLegacyAlertsClient.getTrackedAlerts.mockImplementation(() => ({ + active: { + '1': new Alert('1', { + state: { foo: true }, + meta: { + flapping: false, + flappingHistory: [true, false], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', }, - flapping: false, - flapping_history: [true], - instance: { - id: '1', + }), + '2': new Alert('2', { + state: { foo: false }, + meta: { + flapping: false, + flappingHistory: [true, false, false], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'def', }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, - }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', + }), + }, + recovered: { + '3': new Alert('3', { + state: { foo: false }, + meta: { + flapping: false, + flappingHistory: [true, false, false], + uuid: 'xyz', }, - start: date, - status: 'active', - time_range: { - gte: date, + }), + }, + })); + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + + const alertsClient = new AlertsClient(alertsClientParams); + + const opts = { + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }; + await alertsClient.initializeExecution(opts); + expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); + + expect(clusterClient.search).toHaveBeenCalledWith({ + body: { + query: { + bool: { + filter: [ + { term: { 'kibana.alert.rule.uuid': '1' } }, + { terms: { 'kibana.alert.uuid': ['abc', 'def', 'xyz'] } }, + ], }, - uuid: uuid1, - workflow_status: 'open', }, - space_ids: ['default'], - version: '8.9.0', - }, - tags: ['rule-', '-tags'], - }, - { index: { _id: uuid2 } }, - // new alert doc - { - '@timestamp': date, - event: { - action: 'open', - kind: 'signal', + seq_no_primary_term: true, + size: 3, }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', - }, - flapping: false, - flapping_history: [true], - instance: { - id: '2', + index: useDataStreamForAlerts + ? '.alerts-test.alerts-default' + : '.internal.alerts-test.alerts-default-*', + ignore_unavailable: true, + }); + + spy.mockRestore(); + }); + + test('should split queries into chunks when there are greater than 10,000 alert UUIDs', async () => { + mockLegacyAlertsClient.getTrackedAlerts.mockImplementation(() => ({ + active: range(15000).reduce((acc: Record>, value: number) => { + const id: string = `${value}`; + acc[id] = new Alert(id, { + state: { foo: true }, + meta: { + flapping: false, + flappingHistory: [true, false], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: id, }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, - }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', + }); + return acc; + }, {}), + recovered: {}, + })); + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + + const alertsClient = new AlertsClient(alertsClientParams); + + const opts = { + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }; + await alertsClient.initializeExecution(opts); + expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); + + expect(clusterClient.search).toHaveBeenCalledTimes(2); + + spy.mockRestore(); + }); + + test('should log but not throw if query returns error', async () => { + clusterClient.search.mockImplementation(() => { + throw new Error('search failed!'); + }); + mockLegacyAlertsClient.getTrackedAlerts.mockImplementation(() => ({ + active: { + '1': new Alert('1', { + state: { foo: true }, + meta: { + flapping: false, + flappingHistory: [true, false], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', }, - start: date, - status: 'active', - time_range: { - gte: date, + }), + }, + recovered: {}, + })); + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + + const alertsClient = new AlertsClient(alertsClientParams); + + const opts = { + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }; + await alertsClient.initializeExecution(opts); + expect(mockLegacyAlertsClient.initializeExecution).toHaveBeenCalledWith(opts); + + expect(clusterClient.search).toHaveBeenCalledWith({ + body: { + query: { + bool: { + filter: [ + { term: { 'kibana.alert.rule.uuid': '1' } }, + { terms: { 'kibana.alert.uuid': ['abc'] } }, + ], }, - uuid: uuid2, - workflow_status: 'open', }, - space_ids: ['default'], - version: '8.9.0', + size: 1, + seq_no_primary_term: true, }, - tags: ['rule-', '-tags'], - }, - ], + index: useDataStreamForAlerts + ? '.alerts-test.alerts-default' + : '.internal.alerts-test.alerts-default-*', + ignore_unavailable: true, + }); + + expect(logger.error).toHaveBeenCalledWith( + `Error searching for tracked alerts by UUID - search failed!` + ); + + spy.mockRestore(); + }); }); - }); - test('should update ongoing alerts in existing index', async () => { - clusterClient.search.mockResolvedValue({ - took: 10, - timed_out: false, - _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, - hits: { - total: { - relation: 'eq', - value: 1, - }, - hits: [ - { - _id: 'abc', - _index: '.internal.alerts-test.alerts-default-000001', - _source: { - '@timestamp': '2023-03-28T12:27:28.159Z', + describe('persistAlerts()', () => { + test('should index new alerts', async () => { + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); + + // Report 2 new alerts + const alertExecutorService = alertsClient.factory(); + alertExecutorService.create('1').scheduleActions('default'); + alertExecutorService.create('2').scheduleActions('default'); + + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + + await alertsClient.persistAlerts(); + + const { alertsToReturn } = alertsClient.getAlertsToSerialize(); + const uuid1 = alertsToReturn['1'].meta?.uuid; + const uuid2 = alertsToReturn['2'].meta?.uuid; + + expect(clusterClient.bulk).toHaveBeenCalledWith({ + index: '.alerts-test.alerts-default', + refresh: 'wait_for', + require_alias: !useDataStreamForAlerts, + body: [ + { + create: { _id: uuid1, ...(useDataStreamForAlerts ? {} : { require_alias: true }) }, + }, + // new alert doc + { + '@timestamp': date, event: { - action: 'active', + action: 'open', kind: 'signal', }, kibana: { @@ -494,6 +400,7 @@ describe('Alerts Client', () => { instance: { id: '1', }, + maintenance_window_ids: [], rule: { category: 'My test rule', consumer: 'bar', @@ -510,185 +417,25 @@ describe('Alerts Client', () => { tags: ['rule-', '-tags'], uuid: '1', }, - start: '2023-03-28T12:27:28.159Z', + start: date, status: 'active', time_range: { - gte: '2023-03-28T12:27:28.159Z', + gte: date, }, - uuid: 'abc', + uuid: uuid1, workflow_status: 'open', }, space_ids: ['default'], - version: '8.8.0', + version: '8.9.0', }, tags: ['rule-', '-tags'], }, - }, - ], - }, - }); - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: { - '1': { - state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, - meta: { - flapping: false, - flappingHistory: [true], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'abc', - }, - }, - }, - recoveredAlertsFromState: {}, - }); - - // Report 1 new alert and 1 active alert - const alertExecutorService = alertsClient.factory(); - alertExecutorService.create('1').scheduleActions('default'); - alertExecutorService.create('2').scheduleActions('default'); - - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); - - await alertsClient.persistAlerts(); - - const { alertsToReturn } = alertsClient.getAlertsToSerialize(); - const uuid2 = alertsToReturn['2'].meta?.uuid; - - expect(clusterClient.bulk).toHaveBeenCalledWith({ - index: '.alerts-test.alerts-default', - refresh: 'wait_for', - require_alias: true, - body: [ - { - index: { - _id: 'abc', - _index: '.internal.alerts-test.alerts-default-000001', - require_alias: false, - }, - }, - // ongoing alert doc - { - '@timestamp': date, - event: { - action: 'active', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '36000000000000', - }, - flapping: false, - flapping_history: [true, false], - instance: { - id: '1', - }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, - }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', - }, - start: '2023-03-28T12:27:28.159Z', - status: 'active', - time_range: { - gte: '2023-03-28T12:27:28.159Z', - }, - uuid: 'abc', - workflow_status: 'open', - }, - space_ids: ['default'], - version: '8.9.0', - }, - tags: ['rule-', '-tags'], - }, - { index: { _id: uuid2 } }, - // new alert doc - { - '@timestamp': date, - event: { - action: 'open', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', - }, - flapping: false, - flapping_history: [true], - instance: { - id: '2', - }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, - }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', - }, - start: date, - status: 'active', - time_range: { - gte: date, - }, - uuid: uuid2, - workflow_status: 'open', + { + create: { _id: uuid2, ...(useDataStreamForAlerts ? {} : { require_alias: true }) }, }, - space_ids: ['default'], - version: '8.9.0', - }, - tags: ['rule-', '-tags'], - }, - ], - }); - }); - - test('should recover recovered alerts in existing index', async () => { - clusterClient.search.mockResolvedValue({ - took: 10, - timed_out: false, - _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, - hits: { - total: { - relation: 'eq', - value: 1, - }, - hits: [ - { - _id: 'abc', - _index: '.internal.alerts-test.alerts-default-000001', - _source: { - '@timestamp': '2023-03-28T12:27:28.159Z', + // new alert doc + { + '@timestamp': date, event: { action: 'open', kind: 'signal', @@ -702,8 +449,9 @@ describe('Alerts Client', () => { flapping: false, flapping_history: [true], instance: { - id: '1', + id: '2', }, + maintenance_window_ids: [], rule: { category: 'My test rule', consumer: 'bar', @@ -720,25 +468,141 @@ describe('Alerts Client', () => { tags: ['rule-', '-tags'], uuid: '1', }, - start: '2023-03-28T12:27:28.159Z', + start: date, status: 'active', time_range: { - gte: '2023-03-28T12:27:28.159Z', + gte: date, }, - uuid: 'abc', + uuid: uuid2, workflow_status: 'open', }, space_ids: ['default'], - version: '8.8.0', + version: '8.9.0', }, tags: ['rule-', '-tags'], }, + ], + }); + }); + + test('should update ongoing alerts in existing index', async () => { + clusterClient.search.mockResolvedValue({ + took: 10, + timed_out: false, + _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, + hits: { + total: { + relation: 'eq', + value: 1, + }, + hits: [ + { + _id: 'abc', + _index: '.internal.alerts-test.alerts-default-000001', + _seq_no: 41, + _primary_term: 665, + _source: { + '@timestamp': '2023-03-28T12:27:28.159Z', + event: { + action: 'active', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '1', + }, + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T12:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T12:27:28.159Z', + }, + uuid: 'abc', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.8.0', + }, + tags: ['rule-', '-tags'], + }, + }, + ], }, - { - _id: 'def', - _index: '.internal.alerts-test.alerts-default-000002', - _source: { - '@timestamp': '2023-03-28T12:27:28.159Z', + }); + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: { + '1': { + state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, + meta: { + flapping: false, + flappingHistory: [true], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', + }, + }, + }, + recoveredAlertsFromState: {}, + }); + + // Report 1 new alert and 1 active alert + const alertExecutorService = alertsClient.factory(); + alertExecutorService.create('1').scheduleActions('default'); + alertExecutorService.create('2').scheduleActions('default'); + + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + + await alertsClient.persistAlerts(); + + const { alertsToReturn } = alertsClient.getAlertsToSerialize(); + const uuid2 = alertsToReturn['2'].meta?.uuid; + + expect(clusterClient.bulk).toHaveBeenCalledWith({ + index: '.alerts-test.alerts-default', + refresh: 'wait_for', + require_alias: !useDataStreamForAlerts, + body: [ + { + index: { + _id: 'abc', + _index: '.internal.alerts-test.alerts-default-000001', + if_seq_no: 41, + if_primary_term: 665, + require_alias: false, + }, + }, + // ongoing alert doc + { + '@timestamp': date, event: { action: 'active', kind: 'signal', @@ -751,9 +615,61 @@ describe('Alerts Client', () => { }, flapping: false, flapping_history: [true, false], + instance: { + id: '1', + }, + maintenance_window_ids: [], + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T12:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T12:27:28.159Z', + }, + uuid: 'abc', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.9.0', + }, + tags: ['rule-', '-tags'], + }, + { + create: { _id: uuid2, ...(useDataStreamForAlerts ? {} : { require_alias: true }) }, + }, + // new alert doc + { + '@timestamp': date, + event: { + action: 'open', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], instance: { id: '2', }, + maintenance_window_ids: [], rule: { category: 'My test rule', consumer: 'bar', @@ -770,1219 +686,1677 @@ describe('Alerts Client', () => { tags: ['rule-', '-tags'], uuid: '1', }, - start: '2023-03-28T02:27:28.159Z', + start: date, status: 'active', time_range: { - gte: '2023-03-28T02:27:28.159Z', + gte: date, }, - uuid: 'def', + uuid: uuid2, workflow_status: 'open', }, space_ids: ['default'], - version: '8.8.0', + version: '8.9.0', }, tags: ['rule-', '-tags'], }, - }, - ], - }, - }); - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: { - '1': { + ], + }); + }); + + test('should not update ongoing alerts in existing index when they are not in the processed alerts', async () => { + const activeAlert = { state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, meta: { flapping: false, - flappingHistory: [true], + flappingHistory: [true, false], maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, uuid: 'abc', }, - }, - '2': { - state: { foo: true, start: '2023-03-28T02:27:28.159Z', duration: '36000000000000' }, - meta: { - flapping: false, - flappingHistory: [true, false], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'def', + }; + + const activeAlertObj = new Alert<{}, {}, 'default'>('1', activeAlert); + activeAlertObj.scheduleActions('default', {}); + const spy = jest + .spyOn(LegacyAlertsClient.prototype, 'getProcessedAlerts') + .mockReturnValueOnce({ + '1': activeAlertObj, // return only the first (tracked) alert + }) + .mockReturnValueOnce({}); + + clusterClient.search.mockResolvedValue({ + took: 10, + timed_out: false, + _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, + hits: { + total: { + relation: 'eq', + value: 1, + }, + hits: [ + { + _id: 'abc', + _index: '.internal.alerts-test.alerts-default-000001', + _source: { + '@timestamp': '2023-03-28T12:27:28.159Z', + event: { + action: 'active', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '1', + }, + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T12:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T12:27:28.159Z', + }, + uuid: 'abc', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.8.0', + }, + tags: ['rule-', '-tags'], + }, + }, + ], }, - }, - }, - recoveredAlertsFromState: {}, - }); - - // Report 1 new alert and 1 active alert, recover 1 alert - const alertExecutorService = alertsClient.factory(); - alertExecutorService.create('2').scheduleActions('default'); - alertExecutorService.create('3').scheduleActions('default'); - - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); - - await alertsClient.persistAlerts(); - - const { alertsToReturn } = alertsClient.getAlertsToSerialize(); - const uuid3 = alertsToReturn['3'].meta?.uuid; + }); + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: { + '1': activeAlert, + }, + recoveredAlertsFromState: {}, + }); - expect(clusterClient.bulk).toHaveBeenCalledWith({ - index: '.alerts-test.alerts-default', - refresh: 'wait_for', - require_alias: true, - body: [ - { - index: { - _id: 'def', - _index: '.internal.alerts-test.alerts-default-000002', - require_alias: false, - }, - }, - // ongoing alert doc - { - '@timestamp': date, - event: { - action: 'active', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '72000000000000', + // Report 1 new alert and 1 active alert + const alertExecutorService = alertsClient.factory(); + alertExecutorService.create('1').scheduleActions('default'); + alertExecutorService.create('2').scheduleActions('default'); // will be skipped as getProcessedAlerts does not return it + + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + + await alertsClient.persistAlerts(); + + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenNthCalledWith(1, 'active'); + expect(spy).toHaveBeenNthCalledWith(2, 'recovered'); + + expect(logger.error).toHaveBeenCalledWith( + "Error writing alert(2) to .alerts-test.alerts-default - alert(2) doesn't exist in active alerts" + ); + spy.mockRestore(); + + expect(clusterClient.bulk).toHaveBeenCalledWith({ + index: '.alerts-test.alerts-default', + refresh: 'wait_for', + require_alias: !useDataStreamForAlerts, + body: [ + { + create: { + _id: 'abc', + ...(useDataStreamForAlerts ? {} : { require_alias: true }), }, - flapping: false, - flapping_history: [true, false, false], - instance: { - id: '2', + }, + // ongoing alert doc + { + '@timestamp': date, + event: { + action: 'active', + kind: 'signal', }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true, false], + instance: { + id: '1', + }, + maintenance_window_ids: [], + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T12:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T12:27:28.159Z', + }, + uuid: 'abc', + workflow_status: 'open', }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', - }, - start: '2023-03-28T02:27:28.159Z', - status: 'active', - time_range: { - gte: '2023-03-28T02:27:28.159Z', + space_ids: ['default'], + version: '8.9.0', }, - uuid: 'def', - workflow_status: 'open', + tags: ['rule-', '-tags'], }, - space_ids: ['default'], - version: '8.9.0', - }, - tags: ['rule-', '-tags'], - }, - { index: { _id: uuid3 } }, - // new alert doc - { - '@timestamp': date, - event: { - action: 'open', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', - }, - flapping: false, - flapping_history: [true], - instance: { - id: '3', - }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, + ], + }); + }); + + test('should recover recovered alerts in existing index', async () => { + clusterClient.search.mockResolvedValue({ + took: 10, + timed_out: false, + _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, + hits: { + total: { + relation: 'eq', + value: 1, + }, + hits: [ + { + _id: 'abc', + _index: '.internal.alerts-test.alerts-default-000001', + _seq_no: 41, + _primary_term: 665, + _source: { + '@timestamp': '2023-03-28T12:27:28.159Z', + event: { + action: 'open', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '1', + }, + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T12:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T12:27:28.159Z', + }, + uuid: 'abc', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.8.0', + }, + tags: ['rule-', '-tags'], }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', }, - start: date, - status: 'active', - time_range: { - gte: date, + { + _id: 'def', + _index: '.internal.alerts-test.alerts-default-000002', + _seq_no: 42, + _primary_term: 666, + _source: { + '@timestamp': '2023-03-28T12:27:28.159Z', + event: { + action: 'active', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '36000000000000', + }, + flapping: false, + flapping_history: [true, false], + instance: { + id: '2', + }, + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T02:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T02:27:28.159Z', + }, + uuid: 'def', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.8.0', + }, + tags: ['rule-', '-tags'], + }, }, - uuid: uuid3, - workflow_status: 'open', - }, - space_ids: ['default'], - version: '8.9.0', - }, - tags: ['rule-', '-tags'], - }, - { - index: { - _id: 'abc', - _index: '.internal.alerts-test.alerts-default-000001', - require_alias: false, - }, - }, - // recovered alert doc - { - '@timestamp': date, - event: { - action: 'close', - kind: 'signal', + ], }, - kibana: { - alert: { - action_group: 'recovered', - duration: { - us: '36000000000000', - }, - end: date, - flapping: false, - flapping_history: [true, true], - instance: { - id: '1', - }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, - }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', + }); + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: { + '1': { + state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, + meta: { + flapping: false, + flappingHistory: [true], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', }, - start: '2023-03-28T12:27:28.159Z', - status: 'recovered', - time_range: { - gte: '2023-03-28T12:27:28.159Z', - lte: date, + }, + '2': { + state: { foo: true, start: '2023-03-28T02:27:28.159Z', duration: '36000000000000' }, + meta: { + flapping: false, + flappingHistory: [true, false], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'def', }, - uuid: 'abc', - workflow_status: 'open', }, - space_ids: ['default'], - version: '8.9.0', }, - tags: ['rule-', '-tags'], - }, - ], - }); - }); - - test('should not try to index if no alerts', async () => { - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); + recoveredAlertsFromState: {}, + }); - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); + // Report 1 new alert and 1 active alert, recover 1 alert + const alertExecutorService = alertsClient.factory(); + alertExecutorService.create('2').scheduleActions('default'); + alertExecutorService.create('3').scheduleActions('default'); + + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + + await alertsClient.persistAlerts(); + + const { alertsToReturn } = alertsClient.getAlertsToSerialize(); + const uuid3 = alertsToReturn['3'].meta?.uuid; + + expect(clusterClient.bulk).toHaveBeenCalledWith({ + index: '.alerts-test.alerts-default', + refresh: 'wait_for', + require_alias: !useDataStreamForAlerts, + body: [ + { + index: { + _id: 'def', + _index: '.internal.alerts-test.alerts-default-000002', + if_seq_no: 42, + if_primary_term: 666, + require_alias: false, + }, + }, + // ongoing alert doc + { + '@timestamp': date, + event: { + action: 'active', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '72000000000000', + }, + flapping: false, + flapping_history: [true, false, false], + instance: { + id: '2', + }, + maintenance_window_ids: [], + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T02:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T02:27:28.159Z', + }, + uuid: 'def', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.9.0', + }, + tags: ['rule-', '-tags'], + }, + { + create: { _id: uuid3, ...(useDataStreamForAlerts ? {} : { require_alias: true }) }, + }, + // new alert doc + { + '@timestamp': date, + event: { + action: 'open', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '3', + }, + maintenance_window_ids: [], + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: date, + status: 'active', + time_range: { + gte: date, + }, + uuid: uuid3, + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.9.0', + }, + tags: ['rule-', '-tags'], + }, + { + index: { + _id: 'abc', + _index: '.internal.alerts-test.alerts-default-000001', + if_seq_no: 41, + if_primary_term: 665, + require_alias: false, + }, + }, + // recovered alert doc + { + '@timestamp': date, + event: { + action: 'close', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'recovered', + duration: { + us: '36000000000000', + }, + end: date, + flapping: false, + flapping_history: [true, true], + instance: { + id: '1', + }, + maintenance_window_ids: [], + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T12:27:28.159Z', + status: 'recovered', + time_range: { + gte: '2023-03-28T12:27:28.159Z', + lte: date, + }, + uuid: 'abc', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.9.0', + }, + tags: ['rule-', '-tags'], + }, + ], + }); + }); + + test('should not try to index if no alerts', async () => { + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); - // Report no alerts + // Report no alerts - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); - await alertsClient.persistAlerts(); + await alertsClient.persistAlerts(); - expect(clusterClient.bulk).not.toHaveBeenCalled(); - }); + expect(clusterClient.bulk).not.toHaveBeenCalled(); + }); - test('should log if bulk indexing fails for some alerts', async () => { - clusterClient.bulk.mockResponseOnce({ - took: 1, - errors: true, - items: [ - { - index: { - _index: '.internal.alerts-test.alerts-default-000001', - status: 400, - error: { - type: 'action_request_validation_exception', - reason: 'Validation Failed: 1: index is missing;2: type is missing;', + test('should log if bulk indexing fails for some alerts', async () => { + clusterClient.bulk.mockResponseOnce({ + took: 1, + errors: true, + items: [ + { + index: { + _index: '.internal.alerts-test.alerts-default-000001', + status: 400, + error: { + type: 'action_request_validation_exception', + reason: 'Validation Failed: 1: index is missing;2: type is missing;', + }, + }, }, - }, - }, - { - index: { - _index: '.internal.alerts-test.alerts-default-000002', - _id: '1', - _version: 1, - result: 'created', - _shards: { - total: 2, - successful: 1, - failed: 0, + { + index: { + _index: '.internal.alerts-test.alerts-default-000002', + _id: '1', + _version: 1, + result: 'created', + _shards: { + total: 2, + successful: 1, + failed: 0, + }, + status: 201, + _seq_no: 0, + _primary_term: 1, + }, }, - status: 201, - _seq_no: 0, - _primary_term: 1, - }, - }, - ], - }); - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); - - // Report 2 new alerts - const alertExecutorService = alertsClient.factory(); - alertExecutorService.create('1').scheduleActions('default'); - alertExecutorService.create('2').scheduleActions('default'); + ], + }); + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + // Report 2 new alerts + const alertExecutorService = alertsClient.factory(); + alertExecutorService.create('1').scheduleActions('default'); + alertExecutorService.create('2').scheduleActions('default'); - await alertsClient.persistAlerts(); + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); - expect(clusterClient.bulk).toHaveBeenCalled(); - expect(logger.error).toHaveBeenCalledWith( - `Error writing 1 out of 2 alerts - [{\"type\":\"action_request_validation_exception\",\"reason\":\"Validation Failed: 1: index is missing;2: type is missing;\"}]` - ); - }); + await alertsClient.persistAlerts(); - test('should log and swallow error if bulk indexing throws error', async () => { - clusterClient.bulk.mockImplementation(() => { - throw new Error('fail'); - }); - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); + expect(clusterClient.bulk).toHaveBeenCalled(); + expect(logger.error).toHaveBeenCalledWith( + `Error writing 1 out of 2 alerts - [{\"type\":\"action_request_validation_exception\",\"reason\":\"Validation Failed: 1: index is missing;2: type is missing;\"}]` + ); + }); - // Report 2 new alerts - const alertExecutorService = alertsClient.factory(); - alertExecutorService.create('1').scheduleActions('default'); - alertExecutorService.create('2').scheduleActions('default'); + test('should log and swallow error if bulk indexing throws error', async () => { + clusterClient.bulk.mockImplementation(() => { + throw new Error('fail'); + }); + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + // Report 2 new alerts + const alertExecutorService = alertsClient.factory(); + alertExecutorService.create('1').scheduleActions('default'); + alertExecutorService.create('2').scheduleActions('default'); - await alertsClient.persistAlerts(); + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); - expect(clusterClient.bulk).toHaveBeenCalled(); - expect(logger.error).toHaveBeenCalledWith( - `Error writing 2 alerts to .alerts-test.alerts-default - fail` - ); - }); + await alertsClient.persistAlerts(); - test('should not persist alerts if shouldWrite is false', async () => { - alertsClientParams = { - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - ruleType: { - ...ruleType, - alerts: { - ...ruleType.alerts!, - shouldWrite: false, - }, - }, - namespace: 'default', - rule: alertRuleData, - kibanaVersion: '8.9.0', - }; - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - - expect(await alertsClient.persistAlerts()).toBe(void 0); - - expect(logger.debug).toHaveBeenCalledWith( - `Resources registered and installed for test context but "shouldWrite" is set to false.` - ); - expect(clusterClient.bulk).not.toHaveBeenCalled(); - }); - }); + expect(clusterClient.bulk).toHaveBeenCalled(); + expect(logger.error).toHaveBeenCalledWith( + `Error writing 2 alerts to .alerts-test.alerts-default - fail` + ); + }); - // FLAKY: https://github.com/elastic/kibana/issues/163192 - // FLAKY: https://github.com/elastic/kibana/issues/163193 - // FLAKY: https://github.com/elastic/kibana/issues/163194 - // FLAKY: https://github.com/elastic/kibana/issues/163195 - describe.skip('getSummarizedAlerts', () => { - beforeEach(() => { - clusterClient.search.mockReturnValue({ - // @ts-ignore - hits: { total: { value: 0 }, hits: [] }, + test('should not persist alerts if shouldWrite is false', async () => { + alertsClientParams = { + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + ruleType: { + ...ruleType, + alerts: { + ...ruleType.alerts!, + shouldWrite: false, + }, + }, + namespace: 'default', + rule: alertRuleData, + kibanaVersion: '8.9.0', + dataStreamAdapter: getDataStreamAdapter({ useDataStreamForAlerts }), + }; + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + expect(await alertsClient.persistAlerts()).toBe(void 0); + + expect(logger.debug).toHaveBeenCalledWith( + `Resources registered and installed for test context but "shouldWrite" is set to false.` + ); + expect(clusterClient.bulk).not.toHaveBeenCalled(); + }); }); - }); - const excludedAlertInstanceIds = ['1', '2']; - const alertsFilter: AlertsFilter = { - query: { - kql: 'kibana.alert.rule.name:test', - dsl: '{"bool":{"minimum_should_match":1,"should":[{"match":{"kibana.alert.rule.name":"test"}}]}}', - filters: [], - }, - timeframe: { - days: [1, 2, 3, 4, 5, 6, 7], - hours: { start: '08:00', end: '17:00' }, - timezone: 'UTC', - }, - }; - - test('should get the persistent LifeCycle Alerts successfully', async () => { - clusterClient.search - .mockReturnValueOnce({ - // @ts-ignore - hits: { total: { value: 1 }, hits: [mockAAD] }, - }) - .mockReturnValueOnce({ - // @ts-ignore - hits: { total: { value: 1 }, hits: [mockAAD, mockAAD] }, - }) - .mockReturnValueOnce({ - // @ts-ignore - hits: { total: { value: 0 }, hits: [] }, + // FLAKY: https://github.com/elastic/kibana/issues/163192 + // FLAKY: https://github.com/elastic/kibana/issues/163193 + // FLAKY: https://github.com/elastic/kibana/issues/163194 + // FLAKY: https://github.com/elastic/kibana/issues/163195 + describe('getSummarizedAlerts', () => { + beforeEach(() => { + clusterClient.search.mockReturnValue({ + // @ts-ignore + hits: { total: { value: 0 }, hits: [] }, + }); }); - const alertsClient = new AlertsClient(alertsClientParams); - const result = await alertsClient.getSummarizedAlerts(getParamsByExecutionUuid); - - expect(clusterClient.search).toHaveBeenCalledTimes(3); - - expect(result).toEqual({ - new: { - count: 1, - data: [ - { - _id: mockAAD._id, - _index: mockAAD._index, - ...expandFlattenedAlert(mockAAD._source), - }, - ], - }, - ongoing: { - count: 1, - data: [ - { - _id: mockAAD._id, - _index: mockAAD._index, - ...expandFlattenedAlert(mockAAD._source), + const excludedAlertInstanceIds = ['1', '2']; + const alertsFilter: AlertsFilter = { + query: { + kql: 'kibana.alert.rule.name:test', + dsl: '{"bool":{"minimum_should_match":1,"should":[{"match":{"kibana.alert.rule.name":"test"}}]}}', + filters: [], + }, + timeframe: { + days: [1, 2, 3, 4, 5, 6, 7], + hours: { start: '08:00', end: '17:00' }, + timezone: 'UTC', + }, + }; + + test('should get the persistent LifeCycle Alerts successfully', async () => { + clusterClient.search + .mockReturnValueOnce({ + // @ts-ignore + hits: { total: { value: 1 }, hits: [mockAAD] }, + }) + .mockReturnValueOnce({ + // @ts-ignore + hits: { total: { value: 1 }, hits: [mockAAD, mockAAD] }, + }) + .mockReturnValueOnce({ + // @ts-ignore + hits: { total: { value: 0 }, hits: [] }, + }); + + const alertsClient = new AlertsClient(alertsClientParams); + const result = await alertsClient.getSummarizedAlerts(getParamsByExecutionUuid); + + expect(clusterClient.search).toHaveBeenCalledTimes(3); + + expect(result).toEqual({ + new: { + count: 1, + data: [ + { + _id: mockAAD._id, + _index: mockAAD._index, + ...expandFlattenedAlert(mockAAD._source), + }, + ], }, - { - _id: mockAAD._id, - _index: mockAAD._index, - ...expandFlattenedAlert(mockAAD._source), + ongoing: { + count: 1, + data: [ + { + _id: mockAAD._id, + _index: mockAAD._index, + ...expandFlattenedAlert(mockAAD._source), + }, + { + _id: mockAAD._id, + _index: mockAAD._index, + ...expandFlattenedAlert(mockAAD._source), + }, + ], }, - ], - }, - recovered: { count: 0, data: [] }, - }); - }); + recovered: { count: 0, data: [] }, + }); + }); - test('should get the persistent Continual Alerts successfully', async () => { - clusterClient.search.mockReturnValueOnce({ - // @ts-ignore - hits: { total: { value: 1 }, hits: [mockAAD] }, - }); - const alertsClient = new AlertsClient({ - ...alertsClientParams, - ruleType: { - ...alertsClientParams.ruleType, - autoRecoverAlerts: false, - }, - }); + test('should get the persistent Continual Alerts successfully', async () => { + clusterClient.search.mockReturnValueOnce({ + // @ts-ignore + hits: { total: { value: 1 }, hits: [mockAAD] }, + }); + const alertsClient = new AlertsClient({ + ...alertsClientParams, + ruleType: { + ...alertsClientParams.ruleType, + autoRecoverAlerts: false, + }, + }); - const result = await alertsClient.getSummarizedAlerts(getParamsByExecutionUuid); + const result = await alertsClient.getSummarizedAlerts(getParamsByExecutionUuid); - expect(clusterClient.search).toHaveBeenCalledTimes(1); + expect(clusterClient.search).toHaveBeenCalledTimes(1); - expect(result).toEqual({ - new: { - count: 1, - data: [ - { - _id: mockAAD._id, - _index: mockAAD._index, - ...expandFlattenedAlert(mockAAD._source), + expect(result).toEqual({ + new: { + count: 1, + data: [ + { + _id: mockAAD._id, + _index: mockAAD._index, + ...expandFlattenedAlert(mockAAD._source), + }, + ], }, - ], - }, - ongoing: { count: 0, data: [] }, - recovered: { count: 0, data: [] }, - }); - }); + ongoing: { count: 0, data: [] }, + recovered: { count: 0, data: [] }, + }); + }); - test('formats alerts with formatAlert when provided', async () => { - interface AlertData extends RuleAlertData { - 'signal.rule.consumer': string; - } - const alertsClient = new AlertsClient({ - ...alertsClientParams, - ruleType: { - ...alertsClientParams.ruleType, - autoRecoverAlerts: false, - alerts: { - context: 'test', - mappings: { fieldMap: { field: { type: 'keyword', required: false } } }, - shouldWrite: true, - formatAlert: (alert) => { - const alertCopy = { ...alert } as Partial; - alertCopy['kibana.alert.rule.consumer'] = alert['signal.rule.consumer']; - delete alertCopy['signal.rule.consumer']; - return alertCopy; + test('formats alerts with formatAlert when provided', async () => { + interface AlertData extends RuleAlertData { + 'signal.rule.consumer': string; + } + const alertsClient = new AlertsClient({ + ...alertsClientParams, + ruleType: { + ...alertsClientParams.ruleType, + autoRecoverAlerts: false, + alerts: { + context: 'test', + mappings: { fieldMap: { field: { type: 'keyword', required: false } } }, + shouldWrite: true, + formatAlert: (alert) => { + const alertCopy = { ...alert } as Partial; + alertCopy['kibana.alert.rule.consumer'] = alert['signal.rule.consumer']; + delete alertCopy['signal.rule.consumer']; + return alertCopy; + }, + }, }, - }, - }, - }); + }); - clusterClient.search.mockReturnValueOnce({ - // @ts-ignore - hits: { - total: { value: 1 }, - hits: [ - { - ...mockAAD, - _source: { ...mockAAD._source, 'signal.rule.consumer': 'signalConsumer' }, + clusterClient.search.mockReturnValueOnce({ + // @ts-ignore + hits: { + total: { value: 1 }, + hits: [ + { + ...mockAAD, + _source: { ...mockAAD._source, 'signal.rule.consumer': 'signalConsumer' }, + }, + ], }, - ], - }, - }); + }); - const result = await alertsClient.getSummarizedAlerts(getParamsByExecutionUuid); + const result = await alertsClient.getSummarizedAlerts(getParamsByExecutionUuid); - expect(clusterClient.search).toHaveBeenCalledTimes(1); + expect(clusterClient.search).toHaveBeenCalledTimes(1); - const expectedResult = { ...mockAAD._source }; - expectedResult['kibana.alert.rule.consumer'] = 'signalConsumer'; + const expectedResult = { ...mockAAD._source }; + expectedResult['kibana.alert.rule.consumer'] = 'signalConsumer'; - expect(result).toEqual({ - new: { - count: 1, - data: [ - { - _id: mockAAD._id, - _index: mockAAD._index, - ...expandFlattenedAlert(expectedResult), + expect(result).toEqual({ + new: { + count: 1, + data: [ + { + _id: mockAAD._id, + _index: mockAAD._index, + ...expandFlattenedAlert(expectedResult), + }, + ], }, - ], - }, - ongoing: { count: 0, data: [] }, - recovered: { count: 0, data: [] }, - }); - }); + ongoing: { count: 0, data: [] }, + recovered: { count: 0, data: [] }, + }); + }); - describe.each([ - { alertType: 'LifeCycle Alerts Query', isLifecycleAlert: true }, - { alertType: 'Continual Alerts Query', isLifecycleAlert: false }, - ])('$alertType', ({ isLifecycleAlert }) => { - describe.each([ - { - queryByType: 'ByExecutionUuid', - baseParams: getParamsByExecutionUuid, - getQuery: getExpectedQueryByExecutionUuid, - }, - { - queryByType: 'ByTimeRange', - baseParams: getParamsByTimeQuery, - getQuery: getExpectedQueryByTimeRange, - }, - ])('$queryByType', ({ baseParams, getQuery }) => { - test.each([ - { - text: 'should generate the correct query', - params: baseParams, - call1: getQuery({ - alertType: 'new', - isLifecycleAlert, - }), - call2: getQuery({ - alertType: 'ongoing', - }), - call3: getQuery({ - alertType: 'recovered', - }), - }, - { - text: 'should filter by excludedAlertInstanceIds', - params: { - ...baseParams, - excludedAlertInstanceIds, - }, - call1: getQuery({ - alertType: 'new', - isLifecycleAlert, - excludedAlertInstanceIds, - }), - call2: getQuery({ - alertType: 'ongoing', - excludedAlertInstanceIds, - }), - call3: getQuery({ - alertType: 'recovered', - excludedAlertInstanceIds, - }), - }, - { - text: 'should filter by alertsFilter', - params: { - ...baseParams, - alertsFilter, + describe.each([ + { alertType: 'LifeCycle Alerts Query', isLifecycleAlert: true }, + { alertType: 'Continual Alerts Query', isLifecycleAlert: false }, + ])('$alertType', ({ isLifecycleAlert }) => { + describe.each([ + { + queryByType: 'ByExecutionUuid', + baseParams: getParamsByExecutionUuid, + getQuery: getExpectedQueryByExecutionUuid, }, - call1: getQuery({ - alertType: 'new', - isLifecycleAlert, - alertsFilter, - }), - call2: getQuery({ - alertType: 'ongoing', - alertsFilter, - }), - call3: getQuery({ - alertType: 'recovered', - alertsFilter, - }), - }, - { - text: 'alertsFilter uses the all the days (ISO_WEEKDAYS) when no day is selected', - params: { - ...baseParams, - alertsFilter: { - ...alertsFilter, - timeframe: { - ...alertsFilter.timeframe!, - days: [], + { + queryByType: 'ByTimeRange', + baseParams: getParamsByTimeQuery, + getQuery: getExpectedQueryByTimeRange, + }, + ])('$queryByType', ({ baseParams, getQuery }) => { + const indexName = useDataStreamForAlerts + ? '.alerts-test.alerts-default' + : '.internal.alerts-test.alerts-default-*'; + test.each([ + { + text: 'should generate the correct query', + params: baseParams, + call1: getQuery({ + indexName, + alertType: 'new', + isLifecycleAlert, + }), + call2: getQuery({ + indexName, + alertType: 'ongoing', + }), + call3: getQuery({ + indexName, + alertType: 'recovered', + }), + }, + { + text: 'should filter by excludedAlertInstanceIds', + params: { + ...baseParams, + excludedAlertInstanceIds, }, + call1: getQuery({ + indexName, + alertType: 'new', + isLifecycleAlert, + excludedAlertInstanceIds, + }), + call2: getQuery({ + indexName, + alertType: 'ongoing', + excludedAlertInstanceIds, + }), + call3: getQuery({ + indexName, + alertType: 'recovered', + excludedAlertInstanceIds, + }), }, - }, - call1: getQuery({ - alertType: 'new', - isLifecycleAlert, - alertsFilter, - }), - call2: getQuery({ - alertType: 'ongoing', - alertsFilter, - }), - call3: getQuery({ - alertType: 'recovered', - alertsFilter, - }), - }, - ])('$text', async ({ params, call1, call2, call3 }) => { - const alertsClient = new AlertsClient({ - ...alertsClientParams, - ruleType: { - ...alertsClientParams.ruleType, - autoRecoverAlerts: isLifecycleAlert, - }, + { + text: 'should filter by alertsFilter', + params: { + ...baseParams, + alertsFilter, + }, + call1: getQuery({ + indexName, + alertType: 'new', + isLifecycleAlert, + alertsFilter, + }), + call2: getQuery({ + indexName, + alertType: 'ongoing', + alertsFilter, + }), + call3: getQuery({ + indexName, + alertType: 'recovered', + alertsFilter, + }), + }, + { + text: 'alertsFilter uses the all the days (ISO_WEEKDAYS) when no day is selected', + params: { + ...baseParams, + alertsFilter: { + ...alertsFilter, + timeframe: { + ...alertsFilter.timeframe!, + days: [], + }, + }, + }, + call1: getQuery({ + indexName, + alertType: 'new', + isLifecycleAlert, + alertsFilter, + }), + call2: getQuery({ + indexName, + alertType: 'ongoing', + alertsFilter, + }), + call3: getQuery({ + indexName, + alertType: 'recovered', + alertsFilter, + }), + }, + ])('$text', async ({ params, call1, call2, call3 }) => { + const alertsClient = new AlertsClient({ + ...alertsClientParams, + ruleType: { + ...alertsClientParams.ruleType, + autoRecoverAlerts: isLifecycleAlert, + }, + }); + await alertsClient.getSummarizedAlerts(params); + expect(clusterClient.search).toHaveBeenCalledTimes(isLifecycleAlert ? 3 : 1); + expect(clusterClient.search).toHaveBeenNthCalledWith(1, call1); + if (isLifecycleAlert) { + expect(clusterClient.search).toHaveBeenNthCalledWith(2, call2); + expect(clusterClient.search).toHaveBeenNthCalledWith(3, call3); + } + }); }); - await alertsClient.getSummarizedAlerts(params); - expect(clusterClient.search).toHaveBeenCalledTimes(isLifecycleAlert ? 3 : 1); - expect(clusterClient.search).toHaveBeenNthCalledWith(1, call1); - if (isLifecycleAlert) { - expect(clusterClient.search).toHaveBeenNthCalledWith(2, call2); - expect(clusterClient.search).toHaveBeenNthCalledWith(3, call3); - } }); - }); - }); - describe('throws error', () => { - let alertsClient: AlertsClient<{}, {}, {}, 'default', 'recovered'>; + describe('throws error', () => { + let alertsClient: AlertsClient<{}, {}, {}, 'default', 'recovered'>; - beforeEach(() => { - alertsClient = new AlertsClient(alertsClientParams); - }); - test('if ruleId is not specified', async () => { - const { ruleId, ...paramsWithoutRuleId } = getParamsByExecutionUuid; + beforeEach(() => { + alertsClient = new AlertsClient(alertsClientParams); + }); + test('if ruleId is not specified', async () => { + const { ruleId, ...paramsWithoutRuleId } = getParamsByExecutionUuid; - await expect( - alertsClient.getSummarizedAlerts(paramsWithoutRuleId as GetSummarizedAlertsParams) - ).rejects.toThrowError(`Must specify both rule ID and space ID for AAD alert query.`); - }); + await expect( + alertsClient.getSummarizedAlerts(paramsWithoutRuleId as GetSummarizedAlertsParams) + ).rejects.toThrowError(`Must specify both rule ID and space ID for AAD alert query.`); + }); - test('if spaceId is not specified', async () => { - const { spaceId, ...paramsWithoutSpaceId } = getParamsByExecutionUuid; + test('if spaceId is not specified', async () => { + const { spaceId, ...paramsWithoutSpaceId } = getParamsByExecutionUuid; - await expect( - alertsClient.getSummarizedAlerts(paramsWithoutSpaceId as GetSummarizedAlertsParams) - ).rejects.toThrowError(`Must specify both rule ID and space ID for AAD alert query.`); - }); + await expect( + alertsClient.getSummarizedAlerts(paramsWithoutSpaceId as GetSummarizedAlertsParams) + ).rejects.toThrowError(`Must specify both rule ID and space ID for AAD alert query.`); + }); - test('if executionUuid or start date are not specified', async () => { - const { executionUuid, ...paramsWithoutExecutionUuid } = getParamsByExecutionUuid; + test('if executionUuid or start date are not specified', async () => { + const { executionUuid, ...paramsWithoutExecutionUuid } = getParamsByExecutionUuid; - await expect( - alertsClient.getSummarizedAlerts(paramsWithoutExecutionUuid as GetSummarizedAlertsParams) - ).rejects.toThrowError( - 'Must specify either execution UUID or time range for AAD alert query.' - ); - }); + await expect( + alertsClient.getSummarizedAlerts( + paramsWithoutExecutionUuid as GetSummarizedAlertsParams + ) + ).rejects.toThrowError( + 'Must specify either execution UUID or time range for AAD alert query.' + ); + }); - test('if start date is not specified for a TimeRange query', async () => { - const { start, ...paramsWithoutStart } = getParamsByTimeQuery; + test('if start date is not specified for a TimeRange query', async () => { + const { start, ...paramsWithoutStart } = getParamsByTimeQuery; - await expect( - alertsClient.getSummarizedAlerts(paramsWithoutStart as GetSummarizedAlertsParams) - ).rejects.toThrowError( - 'Must specify either execution UUID or time range for AAD alert query.' - ); - }); + await expect( + alertsClient.getSummarizedAlerts(paramsWithoutStart as GetSummarizedAlertsParams) + ).rejects.toThrowError( + 'Must specify either execution UUID or time range for AAD alert query.' + ); + }); - test('if end date is not specified for a TimeRange query', async () => { - const { end, ...paramsWithoutEnd } = getParamsByTimeQuery; + test('if end date is not specified for a TimeRange query', async () => { + const { end, ...paramsWithoutEnd } = getParamsByTimeQuery; - await expect( - alertsClient.getSummarizedAlerts(paramsWithoutEnd as GetSummarizedAlertsParams) - ).rejects.toThrowError( - 'Must specify either execution UUID or time range for AAD alert query.' - ); + await expect( + alertsClient.getSummarizedAlerts(paramsWithoutEnd as GetSummarizedAlertsParams) + ).rejects.toThrowError( + 'Must specify either execution UUID or time range for AAD alert query.' + ); + }); + }); }); - }); - }); - describe('report()', () => { - test('should create legacy alert with id, action group', async () => { - const mockGetUuidCurrent = jest - .fn() - .mockReturnValueOnce('uuid1') - .mockReturnValueOnce('uuid2'); - const mockGetStartCurrent = jest.fn().mockReturnValue(null); - const mockScheduleActionsCurrent = jest.fn().mockImplementation(() => ({ - replaceState: mockReplaceState, - getUuid: mockGetUuidCurrent, - getStart: mockGetStartCurrent, - })); - const mockCreateCurrent = jest.fn().mockImplementation(() => ({ - scheduleActions: mockScheduleActionsCurrent, - })); - mockLegacyAlertsClient.factory.mockImplementation(() => ({ create: mockCreateCurrent })); - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); + describe('report()', () => { + test('should create legacy alert with id, action group', async () => { + const mockGetUuidCurrent = jest + .fn() + .mockReturnValueOnce('uuid1') + .mockReturnValueOnce('uuid2'); + const mockGetStartCurrent = jest.fn().mockReturnValue(null); + const mockScheduleActionsCurrent = jest.fn().mockImplementation(() => ({ + replaceState: mockReplaceState, + getUuid: mockGetUuidCurrent, + getStart: mockGetStartCurrent, + })); + const mockCreateCurrent = jest.fn().mockImplementation(() => ({ + scheduleActions: mockScheduleActionsCurrent, + })); + mockLegacyAlertsClient.factory.mockImplementation(() => ({ create: mockCreateCurrent })); + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); - // Report 2 new alerts - const { uuid: uuid1, start: start1 } = alertsClient.report({ - id: '1', - actionGroup: 'default', - state: {}, - context: {}, - }); - const { uuid: uuid2, start: start2 } = alertsClient.report({ - id: '2', - actionGroup: 'default', - state: {}, - context: {}, - }); + // Report 2 new alerts + const { uuid: uuid1, start: start1 } = alertsClient.report({ + id: '1', + actionGroup: 'default', + state: {}, + context: {}, + }); + const { uuid: uuid2, start: start2 } = alertsClient.report({ + id: '2', + actionGroup: 'default', + state: {}, + context: {}, + }); - expect(mockCreateCurrent).toHaveBeenCalledTimes(2); - expect(mockCreateCurrent).toHaveBeenNthCalledWith(1, '1'); - expect(mockCreateCurrent).toHaveBeenNthCalledWith(2, '2'); - expect(mockScheduleActionsCurrent).toHaveBeenCalledTimes(2); - expect(mockScheduleActionsCurrent).toHaveBeenNthCalledWith(1, 'default', {}); - expect(mockScheduleActionsCurrent).toHaveBeenNthCalledWith(2, 'default', {}); + expect(mockCreateCurrent).toHaveBeenCalledTimes(2); + expect(mockCreateCurrent).toHaveBeenNthCalledWith(1, '1'); + expect(mockCreateCurrent).toHaveBeenNthCalledWith(2, '2'); + expect(mockScheduleActionsCurrent).toHaveBeenCalledTimes(2); + expect(mockScheduleActionsCurrent).toHaveBeenNthCalledWith(1, 'default', {}); + expect(mockScheduleActionsCurrent).toHaveBeenNthCalledWith(2, 'default', {}); - expect(mockReplaceState).not.toHaveBeenCalled(); - spy.mockRestore(); + expect(mockReplaceState).not.toHaveBeenCalled(); + spy.mockRestore(); - expect(uuid1).toEqual('uuid1'); - expect(uuid2).toEqual('uuid2'); - expect(start1).toBeNull(); - expect(start2).toBeNull(); - }); + expect(uuid1).toEqual('uuid1'); + expect(uuid2).toEqual('uuid2'); + expect(start1).toBeNull(); + expect(start2).toBeNull(); + }); - test('should set context if defined', async () => { - mockLegacyAlertsClient.factory.mockImplementation(() => ({ create: mockCreate })); - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - const alertsClient = new AlertsClient<{}, {}, { foo?: string }, 'default', 'recovered'>( - alertsClientParams - ); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); + test('should set context if defined', async () => { + mockLegacyAlertsClient.factory.mockImplementation(() => ({ create: mockCreate })); + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + const alertsClient = new AlertsClient<{}, {}, { foo?: string }, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); - // Report 2 new alerts - alertsClient.report({ - id: '1', - actionGroup: 'default', - state: {}, - context: { foo: 'cheese' }, - }); - alertsClient.report({ id: '2', actionGroup: 'default', state: {}, context: {} }); + // Report 2 new alerts + alertsClient.report({ + id: '1', + actionGroup: 'default', + state: {}, + context: { foo: 'cheese' }, + }); + alertsClient.report({ id: '2', actionGroup: 'default', state: {}, context: {} }); - expect(mockCreate).toHaveBeenCalledTimes(2); - expect(mockCreate).toHaveBeenNthCalledWith(1, '1'); - expect(mockCreate).toHaveBeenNthCalledWith(2, '2'); - expect(mockScheduleActions).toHaveBeenCalledTimes(2); - expect(mockScheduleActions).toHaveBeenNthCalledWith(1, 'default', { foo: 'cheese' }); - expect(mockScheduleActions).toHaveBeenNthCalledWith(2, 'default', {}); + expect(mockCreate).toHaveBeenCalledTimes(2); + expect(mockCreate).toHaveBeenNthCalledWith(1, '1'); + expect(mockCreate).toHaveBeenNthCalledWith(2, '2'); + expect(mockScheduleActions).toHaveBeenCalledTimes(2); + expect(mockScheduleActions).toHaveBeenNthCalledWith(1, 'default', { foo: 'cheese' }); + expect(mockScheduleActions).toHaveBeenNthCalledWith(2, 'default', {}); - expect(mockReplaceState).not.toHaveBeenCalled(); - spy.mockRestore(); - }); + expect(mockReplaceState).not.toHaveBeenCalled(); + spy.mockRestore(); + }); - test('should set state if defined', async () => { - mockLegacyAlertsClient.factory.mockImplementation(() => ({ create: mockCreate })); - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - const alertsClient = new AlertsClient<{}, { count: number }, {}, 'default', 'recovered'>( - alertsClientParams - ); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); + test('should set state if defined', async () => { + mockLegacyAlertsClient.factory.mockImplementation(() => ({ create: mockCreate })); + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + const alertsClient = new AlertsClient<{}, { count: number }, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); - // Report 2 new alerts - alertsClient.report({ id: '1', actionGroup: 'default', state: { count: 1 }, context: {} }); - alertsClient.report({ id: '2', actionGroup: 'default', state: { count: 2 }, context: {} }); - - expect(mockCreate).toHaveBeenCalledTimes(2); - expect(mockCreate).toHaveBeenNthCalledWith(1, '1'); - expect(mockCreate).toHaveBeenNthCalledWith(2, '2'); - expect(mockScheduleActions).toHaveBeenCalledTimes(2); - expect(mockScheduleActions).toHaveBeenNthCalledWith(1, 'default', {}); - expect(mockScheduleActions).toHaveBeenNthCalledWith(2, 'default', {}); - expect(mockReplaceState).toHaveBeenCalledTimes(2); - expect(mockReplaceState).toHaveBeenNthCalledWith(1, { count: 1 }); - expect(mockReplaceState).toHaveBeenNthCalledWith(2, { count: 2 }); - spy.mockRestore(); - }); + // Report 2 new alerts + alertsClient.report({ + id: '1', + actionGroup: 'default', + state: { count: 1 }, + context: {}, + }); + alertsClient.report({ + id: '2', + actionGroup: 'default', + state: { count: 2 }, + context: {}, + }); - test('should set payload if defined and write out to alert doc', async () => { - const alertsClient = new AlertsClient< - { count: number; url: string }, - {}, - {}, - 'default', - 'recovered' - >(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); + expect(mockCreate).toHaveBeenCalledTimes(2); + expect(mockCreate).toHaveBeenNthCalledWith(1, '1'); + expect(mockCreate).toHaveBeenNthCalledWith(2, '2'); + expect(mockScheduleActions).toHaveBeenCalledTimes(2); + expect(mockScheduleActions).toHaveBeenNthCalledWith(1, 'default', {}); + expect(mockScheduleActions).toHaveBeenNthCalledWith(2, 'default', {}); + expect(mockReplaceState).toHaveBeenCalledTimes(2); + expect(mockReplaceState).toHaveBeenNthCalledWith(1, { count: 1 }); + expect(mockReplaceState).toHaveBeenNthCalledWith(2, { count: 2 }); + spy.mockRestore(); + }); - // Report 2 new alerts - alertsClient.report({ - id: '1', - actionGroup: 'default', - state: {}, - context: {}, - payload: { count: 1, url: `https://url1` }, - }); - alertsClient.report({ - id: '2', - actionGroup: 'default', - state: {}, - context: {}, - payload: { count: 2, url: `https://url2` }, - }); + test('should set payload if defined and write out to alert doc', async () => { + const alertsClient = new AlertsClient< + { count: number; url: string }, + {}, + {}, + 'default', + 'recovered' + >(alertsClientParams); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + // Report 2 new alerts + alertsClient.report({ + id: '1', + actionGroup: 'default', + state: {}, + context: {}, + payload: { count: 1, url: `https://url1` }, + }); + alertsClient.report({ + id: '2', + actionGroup: 'default', + state: {}, + context: {}, + payload: { count: 2, url: `https://url2` }, + }); - await alertsClient.persistAlerts(); + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); - const { alertsToReturn } = alertsClient.getAlertsToSerialize(); - const uuid1 = alertsToReturn['1'].meta?.uuid; - const uuid2 = alertsToReturn['2'].meta?.uuid; + await alertsClient.persistAlerts(); - expect(clusterClient.bulk).toHaveBeenCalledWith({ - index: '.alerts-test.alerts-default', - refresh: 'wait_for', - require_alias: true, - body: [ - { index: { _id: uuid1 } }, - // new alert doc - { - '@timestamp': date, - count: 1, - event: { - action: 'open', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', - }, - flapping: false, - flapping_history: [true], - instance: { - id: '1', + const { alertsToReturn } = alertsClient.getAlertsToSerialize(); + const uuid1 = alertsToReturn['1'].meta?.uuid; + const uuid2 = alertsToReturn['2'].meta?.uuid; + + expect(clusterClient.bulk).toHaveBeenCalledWith({ + index: '.alerts-test.alerts-default', + refresh: 'wait_for', + require_alias: !useDataStreamForAlerts, + body: [ + { + create: { _id: uuid1, ...(useDataStreamForAlerts ? {} : { require_alias: true }) }, + }, + // new alert doc + { + '@timestamp': date, + count: 1, + event: { + action: 'open', + kind: 'signal', }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '1', + }, + maintenance_window_ids: [], + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: date, + status: 'active', + time_range: { + gte: date, + }, + uuid: uuid1, + workflow_status: 'open', }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', - }, - start: date, - status: 'active', - time_range: { - gte: date, + space_ids: ['default'], + version: '8.9.0', }, - uuid: uuid1, - workflow_status: 'open', + tags: ['rule-', '-tags'], + url: `https://url1`, }, - space_ids: ['default'], - version: '8.9.0', - }, - tags: ['rule-', '-tags'], - url: `https://url1`, - }, - { index: { _id: uuid2 } }, - // new alert doc - { - '@timestamp': date, - count: 2, - event: { - action: 'open', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', - }, - flapping: false, - flapping_history: [true], - instance: { - id: '2', + { + create: { _id: uuid2, ...(useDataStreamForAlerts ? {} : { require_alias: true }) }, + }, + // new alert doc + { + '@timestamp': date, + count: 2, + event: { + action: 'open', + kind: 'signal', }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '2', + }, + maintenance_window_ids: [], + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: date, + status: 'active', + time_range: { + gte: date, + }, + uuid: uuid2, + workflow_status: 'open', }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', - }, - start: date, - status: 'active', - time_range: { - gte: date, + space_ids: ['default'], + version: '8.9.0', }, - uuid: uuid2, - workflow_status: 'open', + tags: ['rule-', '-tags'], + url: `https://url2`, }, - space_ids: ['default'], - version: '8.9.0', - }, - tags: ['rule-', '-tags'], - url: `https://url2`, - }, - ], + ], + }); + }); }); - }); - }); - describe('setAlertData()', () => { - test('should call setContext on legacy alert', async () => { - mockLegacyAlertsClient.getAlert.mockReturnValueOnce({ - getId: jest.fn().mockReturnValue('1'), - setContext: mockSetContext, - }); - mockLegacyAlertsClient.getAlert.mockReturnValueOnce({ - getId: jest.fn().mockReturnValue('1'), - setContext: mockSetContext, - }); - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: { - '1': { - state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, - meta: { - flapping: false, - flappingHistory: [true], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'abc', - }, - }, - '2': { - state: { foo: true, start: '2023-03-28T02:27:28.159Z', duration: '36000000000000' }, - meta: { - flapping: false, - flappingHistory: [true, false], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'def', + describe('setAlertData()', () => { + test('should call setContext on legacy alert', async () => { + mockLegacyAlertsClient.getAlert.mockReturnValueOnce({ + getId: jest.fn().mockReturnValue('1'), + setContext: mockSetContext, + }); + mockLegacyAlertsClient.getAlert.mockReturnValueOnce({ + getId: jest.fn().mockReturnValue('1'), + setContext: mockSetContext, + }); + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: { + '1': { + state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, + meta: { + flapping: false, + flappingHistory: [true], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', + }, + }, + '2': { + state: { foo: true, start: '2023-03-28T02:27:28.159Z', duration: '36000000000000' }, + meta: { + flapping: false, + flappingHistory: [true, false], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'def', + }, + }, }, - }, - }, - recoveredAlertsFromState: {}, - }); + recoveredAlertsFromState: {}, + }); - // Set context on 2 recovered alerts - alertsClient.setAlertData({ id: '1', context: { foo: 'bar' } }); - alertsClient.setAlertData({ id: '2' }); + // Set context on 2 recovered alerts + alertsClient.setAlertData({ id: '1', context: { foo: 'bar' } }); + alertsClient.setAlertData({ id: '2' }); - expect(mockSetContext).toHaveBeenCalledTimes(2); - expect(mockSetContext).toHaveBeenNthCalledWith(1, { foo: 'bar' }); - expect(mockSetContext).toHaveBeenNthCalledWith(2, {}); - spy.mockRestore(); - }); + expect(mockSetContext).toHaveBeenCalledTimes(2); + expect(mockSetContext).toHaveBeenNthCalledWith(1, { foo: 'bar' }); + expect(mockSetContext).toHaveBeenNthCalledWith(2, {}); + spy.mockRestore(); + }); - test('should throw error if called on unknown alert id', async () => { - mockLegacyAlertsClient.getAlert.mockReturnValueOnce(null); - const spy = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - const alertsClient = new AlertsClient<{}, {}, { foo?: string }, 'default', 'recovered'>( - alertsClientParams - ); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: { - '1': { - state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, - meta: { - flapping: false, - flappingHistory: [true], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'abc', - }, - }, - '2': { - state: { foo: true, start: '2023-03-28T02:27:28.159Z', duration: '36000000000000' }, - meta: { - flapping: false, - flappingHistory: [true, false], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'def', + test('should throw error if called on unknown alert id', async () => { + mockLegacyAlertsClient.getAlert.mockReturnValueOnce(null); + const spy = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + const alertsClient = new AlertsClient<{}, {}, { foo?: string }, 'default', 'recovered'>( + alertsClientParams + ); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: { + '1': { + state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, + meta: { + flapping: false, + flappingHistory: [true], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', + }, + }, + '2': { + state: { foo: true, start: '2023-03-28T02:27:28.159Z', duration: '36000000000000' }, + meta: { + flapping: false, + flappingHistory: [true, false], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'def', + }, + }, }, - }, - }, - recoveredAlertsFromState: {}, - }); + recoveredAlertsFromState: {}, + }); - // Set context on 2 recovered alerts - expect(() => { - alertsClient.setAlertData({ id: '1', context: { foo: 'bar' } }); - }).toThrowErrorMatchingInlineSnapshot( - `"Cannot set alert data for alert 1 because it has not been reported and it is not recovered."` - ); - spy.mockRestore(); - }); + // Set context on 2 recovered alerts + expect(() => { + alertsClient.setAlertData({ id: '1', context: { foo: 'bar' } }); + }).toThrowErrorMatchingInlineSnapshot( + `"Cannot set alert data for alert 1 because it has not been reported and it is not recovered."` + ); + spy.mockRestore(); + }); - test('should successfully update context and payload for new alert', async () => { - clusterClient.search.mockResolvedValue({ - took: 10, - timed_out: false, - _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, - hits: { - total: { - relation: 'eq', - value: 0, - }, - hits: [], - }, - }); - const alertsClient = new AlertsClient< - { count: number; url: string }, - {}, - {}, - 'default', - 'recovered' - >(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); + test('should successfully update context and payload for new alert', async () => { + clusterClient.search.mockResolvedValue({ + took: 10, + timed_out: false, + _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, + hits: { + total: { + relation: 'eq', + value: 0, + }, + hits: [], + }, + }); + const alertsClient = new AlertsClient< + { count: number; url: string }, + {}, + {}, + 'default', + 'recovered' + >(alertsClientParams); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); - // Report new alert - alertsClient.report({ - id: '1', - actionGroup: 'default', - context: { foo: 'bar' }, - payload: { count: 1, url: `http://localhost:5601` }, - }); + // Report new alert + alertsClient.report({ + id: '1', + actionGroup: 'default', + context: { foo: 'bar' }, + payload: { count: 1, url: `http://localhost:5601` }, + }); - // Update context and payload on the new alert - alertsClient.setAlertData({ - id: '1', - context: { foo: 'notbar' }, - payload: { count: 100, url: `https://elastic.co` }, - }); + // Update context and payload on the new alert + alertsClient.setAlertData({ + id: '1', + context: { foo: 'notbar' }, + payload: { count: 100, url: `https://elastic.co` }, + }); - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); - await alertsClient.persistAlerts(); + await alertsClient.persistAlerts(); - expect(clusterClient.bulk).toHaveBeenCalledWith({ - index: '.alerts-test.alerts-default', - refresh: 'wait_for', - require_alias: true, - body: [ - { - index: { - _id: expect.any(String), - }, - }, - { - '@timestamp': date, - count: 100, - event: { - action: 'open', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', + expect(clusterClient.bulk).toHaveBeenCalledWith({ + index: '.alerts-test.alerts-default', + refresh: 'wait_for', + require_alias: !useDataStreamForAlerts, + body: [ + { + create: { + _id: expect.any(String), + ...(useDataStreamForAlerts ? {} : { require_alias: true }), }, - flapping: false, - flapping_history: [true], - instance: { - id: '1', + }, + { + '@timestamp': date, + count: 100, + event: { + action: 'open', + kind: 'signal', }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '1', + }, + maintenance_window_ids: [], + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: date, + status: 'active', + time_range: { + gte: date, + }, + uuid: expect.any(String), + workflow_status: 'open', }, - name: 'rule-name', - parameters: { - bar: true, + space_ids: ['default'], + version: '8.9.0', + }, + tags: ['rule-', '-tags'], + url: 'https://elastic.co', + }, + ], + }); + }); + + test('should successfully update context and payload for ongoing alert', async () => { + clusterClient.search.mockResolvedValue({ + took: 10, + timed_out: false, + _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, + hits: { + total: { + relation: 'eq', + value: 1, + }, + hits: [ + { + _id: 'abc', + _index: '.internal.alerts-test.alerts-default-000001', + _source: { + '@timestamp': '2023-03-28T12:27:28.159Z', + count: 1, + url: 'https://localhost:5601/abc', + event: { + action: 'active', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '1', + }, + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T12:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T12:27:28.159Z', + }, + uuid: 'abc', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.8.0', + }, + tags: ['rule-', '-tags'], }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', }, - start: date, - status: 'active', - time_range: { - gte: date, + ], + }, + }); + const alertsClient = new AlertsClient< + { count: number; url: string }, + {}, + {}, + 'default', + 'recovered' + >(alertsClientParams); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: { + '1': { + state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, + meta: { + flapping: false, + flappingHistory: [true], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', }, - uuid: expect.any(String), - workflow_status: 'open', }, - space_ids: ['default'], - version: '8.9.0', }, - tags: ['rule-', '-tags'], - url: 'https://elastic.co', - }, - ], - }); - }); + recoveredAlertsFromState: {}, + }); - test('should successfully update context and payload for ongoing alert', async () => { - clusterClient.search.mockResolvedValue({ - took: 10, - timed_out: false, - _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, - hits: { - total: { - relation: 'eq', - value: 1, - }, - hits: [ - { - _id: 'abc', - _index: '.internal.alerts-test.alerts-default-000001', - _source: { - '@timestamp': '2023-03-28T12:27:28.159Z', - count: 1, - url: 'https://localhost:5601/abc', + // Report ongoing alert + alertsClient.report({ + id: '1', + actionGroup: 'default', + context: { foo: 'bar' }, + payload: { count: 1, url: `http://localhost:5601` }, + }); + + // Update context and payload on the new alert + alertsClient.setAlertData({ + id: '1', + context: { foo: 'notbar' }, + payload: { count: 100, url: `https://elastic.co` }, + }); + + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + + await alertsClient.persistAlerts(); + + expect(clusterClient.bulk).toHaveBeenCalledWith({ + index: '.alerts-test.alerts-default', + refresh: 'wait_for', + require_alias: !useDataStreamForAlerts, + body: [ + { + create: { + _id: 'abc', + ...(useDataStreamForAlerts ? {} : { require_alias: true }), + }, + }, + { + '@timestamp': date, + count: 100, event: { action: 'active', kind: 'signal', @@ -1991,13 +2365,14 @@ describe('Alerts Client', () => { alert: { action_group: 'default', duration: { - us: '0', + us: '36000000000000', }, flapping: false, - flapping_history: [true], + flapping_history: [true, false], instance: { id: '1', }, + maintenance_window_ids: [], rule: { category: 'My test rule', consumer: 'bar', @@ -2023,158 +2398,157 @@ describe('Alerts Client', () => { workflow_status: 'open', }, space_ids: ['default'], - version: '8.8.0', + version: '8.9.0', }, tags: ['rule-', '-tags'], + url: 'https://elastic.co', }, - }, - ], - }, - }); - const alertsClient = new AlertsClient< - { count: number; url: string }, - {}, - {}, - 'default', - 'recovered' - >(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: { - '1': { - state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, - meta: { - flapping: false, - flappingHistory: [true], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'abc', - }, - }, - }, - recoveredAlertsFromState: {}, - }); - - // Report ongoing alert - alertsClient.report({ - id: '1', - actionGroup: 'default', - context: { foo: 'bar' }, - payload: { count: 1, url: `http://localhost:5601` }, - }); - - // Update context and payload on the new alert - alertsClient.setAlertData({ - id: '1', - context: { foo: 'notbar' }, - payload: { count: 100, url: `https://elastic.co` }, - }); - - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); - - await alertsClient.persistAlerts(); + ], + }); + }); - expect(clusterClient.bulk).toHaveBeenCalledWith({ - index: '.alerts-test.alerts-default', - refresh: 'wait_for', - require_alias: true, - body: [ - { - index: { - _id: 'abc', - _index: '.internal.alerts-test.alerts-default-000001', - require_alias: false, - }, - }, - { - '@timestamp': date, - count: 100, - event: { - action: 'active', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '36000000000000', - }, - flapping: false, - flapping_history: [true, false], - instance: { - id: '1', - }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, + test('should successfully update context and payload for recovered alert', async () => { + clusterClient.search.mockResolvedValue({ + took: 10, + timed_out: false, + _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, + hits: { + total: { + relation: 'eq', + value: 1, + }, + hits: [ + { + _id: 'abc', + _index: '.internal.alerts-test.alerts-default-000001', + _seq_no: 42, + _primary_term: 666, + _source: { + '@timestamp': '2023-03-28T12:27:28.159Z', + count: 1, + url: 'https://localhost:5601/abc', + event: { + action: 'active', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '1', + }, + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T11:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T11:27:28.159Z', + }, + uuid: 'abc', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.8.0', + }, + tags: ['rule-', '-tags'], }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', }, - start: '2023-03-28T12:27:28.159Z', - status: 'active', - time_range: { - gte: '2023-03-28T12:27:28.159Z', + ], + }, + }); + const alertsClient = new AlertsClient< + { count: number; url: string }, + {}, + {}, + 'default', + 'recovered' + >(alertsClientParams); + + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: { + '1': { + state: { foo: true, start: '2023-03-28T11:27:28.159Z', duration: '0' }, + meta: { + flapping: false, + flappingHistory: [true], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', }, - uuid: 'abc', - workflow_status: 'open', }, - space_ids: ['default'], - version: '8.9.0', }, - tags: ['rule-', '-tags'], - url: 'https://elastic.co', - }, - ], - }); - }); + recoveredAlertsFromState: {}, + }); - test('should successfully update context and payload for recovered alert', async () => { - clusterClient.search.mockResolvedValue({ - took: 10, - timed_out: false, - _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, - hits: { - total: { - relation: 'eq', - value: 1, - }, - hits: [ - { - _id: 'abc', - _index: '.internal.alerts-test.alerts-default-000001', - _source: { - '@timestamp': '2023-03-28T12:27:28.159Z', - count: 1, - url: 'https://localhost:5601/abc', + // Don't report any alerts so existing alert recovers + + // Update context and payload on the new alert + alertsClient.setAlertData({ + id: '1', + context: { foo: 'notbar' }, + payload: { count: 100, url: `https://elastic.co` }, + }); + + alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + + await alertsClient.persistAlerts(); + + expect(clusterClient.bulk).toHaveBeenCalledWith({ + index: '.alerts-test.alerts-default', + refresh: 'wait_for', + require_alias: !useDataStreamForAlerts, + body: [ + { + index: { + _id: 'abc', + if_primary_term: 666, + if_seq_no: 42, + _index: '.internal.alerts-test.alerts-default-000001', + require_alias: false, + }, + }, + { + '@timestamp': date, + count: 100, event: { - action: 'active', + action: 'close', kind: 'signal', }, kibana: { alert: { - action_group: 'default', + action_group: 'recovered', duration: { - us: '0', + us: '39600000000000', }, + end: date, flapping: false, - flapping_history: [true], + flapping_history: [true, true], instance: { id: '1', }, + maintenance_window_ids: [], rule: { category: 'My test rule', consumer: 'bar', @@ -2192,94 +2566,162 @@ describe('Alerts Client', () => { uuid: '1', }, start: '2023-03-28T11:27:28.159Z', - status: 'active', + status: 'recovered', time_range: { gte: '2023-03-28T11:27:28.159Z', + lte: date, }, uuid: 'abc', workflow_status: 'open', }, space_ids: ['default'], - version: '8.8.0', + version: '8.9.0', }, tags: ['rule-', '-tags'], + url: 'https://elastic.co', }, - }, - ], - }, - }); - const alertsClient = new AlertsClient< - { count: number; url: string }, - {}, - {}, - 'default', - 'recovered' - >(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: { - '1': { - state: { foo: true, start: '2023-03-28T11:27:28.159Z', duration: '0' }, - meta: { - flapping: false, - flappingHistory: [true], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'abc', - }, - }, - }, - recoveredAlertsFromState: {}, + ], + }); + }); }); - // Don't report any alerts so existing alert recovers + describe('client()', () => { + test('only returns subset of functionality', async () => { + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); - // Update context and payload on the new alert - alertsClient.setAlertData({ - id: '1', - context: { foo: 'notbar' }, - payload: { count: 100, url: `https://elastic.co` }, - }); + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: {}, + recoveredAlertsFromState: {}, + }); - alertsClient.processAndLogAlerts(processAndLogAlertsOpts); + const publicAlertsClient = alertsClient.client(); - await alertsClient.persistAlerts(); + expect(keys(publicAlertsClient)).toEqual([ + 'report', + 'setAlertData', + 'getAlertLimitValue', + 'setAlertLimitReached', + 'getRecoveredAlerts', + ]); + }); - expect(clusterClient.bulk).toHaveBeenCalledWith({ - index: '.alerts-test.alerts-default', - refresh: 'wait_for', - require_alias: true, - body: [ - { - index: { - _id: 'abc', - _index: '.internal.alerts-test.alerts-default-000001', - require_alias: false, + test('should return recovered alert document with recovered alert, if it exists', async () => { + clusterClient.search.mockResolvedValue({ + took: 10, + timed_out: false, + _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, + hits: { + total: { + relation: 'eq', + value: 1, + }, + hits: [ + { + _id: 'abc', + _index: '.internal.alerts-test.alerts-default-000001', + _source: { + '@timestamp': '2023-03-28T12:27:28.159Z', + event: { + action: 'active', + kind: 'signal', + }, + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '1', + }, + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test.rule-type', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: '2023-03-28T12:27:28.159Z', + status: 'active', + time_range: { + gte: '2023-03-28T12:27:28.159Z', + }, + uuid: 'abc', + workflow_status: 'open', + }, + space_ids: ['default'], + version: '8.8.0', + }, + tags: ['rule-', '-tags'], + }, + }, + ], }, - }, - { - '@timestamp': date, - count: 100, + }); + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: { + '1': { + state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, + meta: { + flapping: false, + flappingHistory: [true], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', + }, + }, + }, + recoveredAlertsFromState: {}, + }); + + // report no alerts to allow existing alert to recover + + const publicAlertsClient = alertsClient.client(); + const recoveredAlerts = publicAlertsClient.getRecoveredAlerts(); + expect(recoveredAlerts.length).toEqual(1); + const recoveredAlert = recoveredAlerts[0]; + expect(recoveredAlert.alert.getId()).toEqual('1'); + expect(recoveredAlert.alert.getUuid()).toEqual('abc'); + expect(recoveredAlert.alert.getStart()).toEqual('2023-03-28T12:27:28.159Z'); + expect(recoveredAlert.hit).toEqual({ + '@timestamp': '2023-03-28T12:27:28.159Z', event: { - action: 'close', + action: 'active', kind: 'signal', }, kibana: { alert: { - action_group: 'recovered', + action_group: 'default', duration: { - us: '39600000000000', + us: '0', }, - end: date, flapping: false, - flapping_history: [true, true], + flapping_history: [true], instance: { id: '1', }, - maintenance_window_ids: [], rule: { category: 'My test rule', consumer: 'bar', @@ -2296,233 +2738,68 @@ describe('Alerts Client', () => { tags: ['rule-', '-tags'], uuid: '1', }, - start: '2023-03-28T11:27:28.159Z', - status: 'recovered', + start: '2023-03-28T12:27:28.159Z', + status: 'active', time_range: { - gte: '2023-03-28T11:27:28.159Z', - lte: date, + gte: '2023-03-28T12:27:28.159Z', }, uuid: 'abc', workflow_status: 'open', }, space_ids: ['default'], - version: '8.9.0', + version: '8.8.0', }, tags: ['rule-', '-tags'], - url: 'https://elastic.co', - }, - ], - }); - }); - }); - - describe('client()', () => { - test('only returns subset of functionality', async () => { - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: {}, - recoveredAlertsFromState: {}, - }); - - const publicAlertsClient = alertsClient.client(); - - expect(keys(publicAlertsClient)).toEqual([ - 'report', - 'setAlertData', - 'getAlertLimitValue', - 'setAlertLimitReached', - 'getRecoveredAlerts', - ]); - }); + }); + }); - test('should return recovered alert document with recovered alert, if it exists', async () => { - clusterClient.search.mockResolvedValue({ - took: 10, - timed_out: false, - _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, - hits: { - total: { - relation: 'eq', - value: 1, - }, - hits: [ - { - _id: 'abc', - _index: '.internal.alerts-test.alerts-default-000001', - _source: { - '@timestamp': '2023-03-28T12:27:28.159Z', - event: { - action: 'active', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', - }, - flapping: false, - flapping_history: [true], - instance: { - id: '1', - }, - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, - }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', - }, - start: '2023-03-28T12:27:28.159Z', - status: 'active', - time_range: { - gte: '2023-03-28T12:27:28.159Z', - }, - uuid: 'abc', - workflow_status: 'open', - }, - space_ids: ['default'], - version: '8.8.0', - }, - tags: ['rule-', '-tags'], + test('should return undefined document with recovered alert, if it does not exists', async () => { + clusterClient.search.mockResolvedValue({ + took: 10, + timed_out: false, + _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, + hits: { + total: { + relation: 'eq', + value: 0, }, + hits: [], }, - ], - }, - }); - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: { - '1': { - state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, - meta: { - flapping: false, - flappingHistory: [true], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'abc', - }, - }, - }, - recoveredAlertsFromState: {}, - }); - - // report no alerts to allow existing alert to recover - - const publicAlertsClient = alertsClient.client(); - const recoveredAlerts = publicAlertsClient.getRecoveredAlerts(); - expect(recoveredAlerts.length).toEqual(1); - const recoveredAlert = recoveredAlerts[0]; - expect(recoveredAlert.alert.getId()).toEqual('1'); - expect(recoveredAlert.alert.getUuid()).toEqual('abc'); - expect(recoveredAlert.alert.getStart()).toEqual('2023-03-28T12:27:28.159Z'); - expect(recoveredAlert.hit).toEqual({ - '@timestamp': '2023-03-28T12:27:28.159Z', - event: { - action: 'active', - kind: 'signal', - }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', - }, - flapping: false, - flapping_history: [true], - instance: { - id: '1', - }, - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - name: 'rule-name', - parameters: { - bar: true, + }); + const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>( + alertsClientParams + ); + await alertsClient.initializeExecution({ + maxAlerts, + ruleLabel: `test: rule-name`, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, + activeAlertsFromState: { + '1': { + state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, + meta: { + flapping: false, + flappingHistory: [true], + maintenanceWindowIds: [], + lastScheduledActions: { group: 'default', date: new Date().toISOString() }, + uuid: 'abc', + }, }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test.rule-type', - tags: ['rule-', '-tags'], - uuid: '1', - }, - start: '2023-03-28T12:27:28.159Z', - status: 'active', - time_range: { - gte: '2023-03-28T12:27:28.159Z', - }, - uuid: 'abc', - workflow_status: 'open', - }, - space_ids: ['default'], - version: '8.8.0', - }, - tags: ['rule-', '-tags'], - }); - }); - - test('should return undefined document with recovered alert, if it does not exists', async () => { - clusterClient.search.mockResolvedValue({ - took: 10, - timed_out: false, - _shards: { failed: 0, successful: 1, total: 1, skipped: 0 }, - hits: { - total: { - relation: 'eq', - value: 0, - }, - hits: [], - }, - }); - const alertsClient = new AlertsClient<{}, {}, {}, 'default', 'recovered'>(alertsClientParams); - await alertsClient.initializeExecution({ - maxAlerts, - ruleLabel: `test: rule-name`, - flappingSettings: DEFAULT_FLAPPING_SETTINGS, - activeAlertsFromState: { - '1': { - state: { foo: true, start: '2023-03-28T12:27:28.159Z', duration: '0' }, - meta: { - flapping: false, - flappingHistory: [true], - maintenanceWindowIds: [], - lastScheduledActions: { group: 'default', date: new Date() }, - uuid: 'abc', }, - }, - }, - recoveredAlertsFromState: {}, - }); + recoveredAlertsFromState: {}, + }); - // report no alerts to allow existing alert to recover + // report no alerts to allow existing alert to recover - const publicAlertsClient = alertsClient.client(); - const recoveredAlerts = publicAlertsClient.getRecoveredAlerts(); - expect(recoveredAlerts.length).toEqual(1); - const recoveredAlert = recoveredAlerts[0]; - expect(recoveredAlert.alert.getId()).toEqual('1'); - expect(recoveredAlert.alert.getUuid()).toEqual('abc'); - expect(recoveredAlert.alert.getStart()).toEqual('2023-03-28T12:27:28.159Z'); - expect(recoveredAlert.hit).toBeUndefined(); + const publicAlertsClient = alertsClient.client(); + const recoveredAlerts = publicAlertsClient.getRecoveredAlerts(); + expect(recoveredAlerts.length).toEqual(1); + const recoveredAlert = recoveredAlerts[0]; + expect(recoveredAlert.alert.getId()).toEqual('1'); + expect(recoveredAlert.alert.getUuid()).toEqual('abc'); + expect(recoveredAlert.alert.getStart()).toEqual('2023-03-28T12:27:28.159Z'); + expect(recoveredAlert.hit).toBeUndefined(); + }); + }); }); - }); + } }); diff --git a/x-pack/plugins/alerting/server/alerts_client/alerts_client.ts b/x-pack/plugins/alerting/server/alerts_client/alerts_client.ts index b79291ff7794b..03500c8b94575 100644 --- a/x-pack/plugins/alerting/server/alerts_client/alerts_client.ts +++ b/x-pack/plugins/alerting/server/alerts_client/alerts_client.ts @@ -19,6 +19,7 @@ import { AlertInstanceState, RuleAlertData, WithoutReservedActionGroups, + DataStreamAdapter, } from '../types'; import { LegacyAlertsClient } from './legacy_alerts_client'; import { @@ -54,6 +55,7 @@ const CHUNK_SIZE = 10000; export interface AlertsClientParams extends CreateAlertsClientParams { elasticsearchClientPromise: Promise; kibanaVersion: string; + dataStreamAdapter: DataStreamAdapter; } export class AlertsClient< @@ -78,6 +80,8 @@ export class AlertsClient< private fetchedAlerts: { indices: Record; data: Record; + seqNo: Record; + primaryTerm: Record; }; private rule: AlertRule = {}; @@ -86,6 +90,7 @@ export class AlertsClient< private indexTemplateAndPattern: IIndexPatternString; private reportedAlerts: Record> = {}; + private _isUsingDataStreams: boolean; constructor(private readonly options: AlertsClientParams) { this.legacyAlertsClient = new LegacyAlertsClient< @@ -100,9 +105,10 @@ export class AlertsClient< ? this.options.namespace : DEFAULT_NAMESPACE_STRING, }); - this.fetchedAlerts = { indices: {}, data: {} }; + this.fetchedAlerts = { indices: {}, data: {}, seqNo: {}, primaryTerm: {} }; this.rule = formatRule({ rule: this.options.rule, ruleType: this.options.ruleType }); this.ruleType = options.ruleType; + this._isUsingDataStreams = this.options.dataStreamAdapter.isUsingDataStreams(); } public async initializeExecution(opts: InitializeExecutionOpts) { @@ -131,6 +137,7 @@ export class AlertsClient< const queryByUuid = async (uuids: string[]) => { const result = await this.search({ size: uuids.length, + seq_no_primary_term: true, query: { bool: { filter: [ @@ -166,6 +173,8 @@ export class AlertsClient< // Keep track of index so we can update the correct document this.fetchedAlerts.indices[alertUuid] = hit._index; + this.fetchedAlerts.seqNo[alertUuid] = hit._seq_no; + this.fetchedAlerts.primaryTerm[alertUuid] = hit._primary_term; } } catch (err) { this.options.logger.error(`Error searching for tracked alerts by UUID - ${err.message}`); @@ -174,11 +183,15 @@ export class AlertsClient< public async search(queryBody: SearchRequest['body']): Promise> { const esClient = await this.options.elasticsearchClientPromise; + const index = this.isUsingDataStreams() + ? this.indexTemplateAndPattern.alias + : this.indexTemplateAndPattern.pattern; const { hits: { hits, total }, } = await esClient.search({ - index: this.indexTemplateAndPattern.pattern, + index, body: queryBody, + ignore_unavailable: true, }); return { hits, total }; @@ -271,8 +284,8 @@ export class AlertsClient< const { alertsToReturn, recoveredAlertsToReturn } = this.legacyAlertsClient.getAlertsToSerialize(false); - const activeAlerts = this.legacyAlertsClient.getProcessedAlerts('activeCurrent'); - const recoveredAlerts = this.legacyAlertsClient.getProcessedAlerts('recoveredCurrent'); + const activeAlerts = this.legacyAlertsClient.getProcessedAlerts('active'); + const recoveredAlerts = this.legacyAlertsClient.getProcessedAlerts('recovered'); // TODO - Lifecycle alerts set some other fields based on alert status // Example: workflow status - default to 'open' if not set @@ -281,41 +294,47 @@ export class AlertsClient< const activeAlertsToIndex: Array = []; for (const id of keys(alertsToReturn)) { // See if there's an existing active alert document - if ( - this.fetchedAlerts.data.hasOwnProperty(id) && - this.fetchedAlerts.data[id].kibana.alert.status === 'active' - ) { - activeAlertsToIndex.push( - buildOngoingAlert< - AlertData, - LegacyState, - LegacyContext, - ActionGroupIds, - RecoveryActionGroupId - >({ - alert: this.fetchedAlerts.data[id], - legacyAlert: activeAlerts[id], - rule: this.rule, - timestamp: currentTime, - payload: this.reportedAlerts[id], - kibanaVersion: this.options.kibanaVersion, - }) - ); + if (!!activeAlerts[id]) { + if ( + this.fetchedAlerts.data.hasOwnProperty(id) && + this.fetchedAlerts.data[id].kibana.alert.status === 'active' + ) { + activeAlertsToIndex.push( + buildOngoingAlert< + AlertData, + LegacyState, + LegacyContext, + ActionGroupIds, + RecoveryActionGroupId + >({ + alert: this.fetchedAlerts.data[id], + legacyAlert: activeAlerts[id], + rule: this.rule, + timestamp: currentTime, + payload: this.reportedAlerts[id], + kibanaVersion: this.options.kibanaVersion, + }) + ); + } else { + activeAlertsToIndex.push( + buildNewAlert< + AlertData, + LegacyState, + LegacyContext, + ActionGroupIds, + RecoveryActionGroupId + >({ + legacyAlert: activeAlerts[id], + rule: this.rule, + timestamp: currentTime, + payload: this.reportedAlerts[id], + kibanaVersion: this.options.kibanaVersion, + }) + ); + } } else { - activeAlertsToIndex.push( - buildNewAlert< - AlertData, - LegacyState, - LegacyContext, - ActionGroupIds, - RecoveryActionGroupId - >({ - legacyAlert: activeAlerts[id], - rule: this.rule, - timestamp: currentTime, - payload: this.reportedAlerts[id], - kibanaVersion: this.options.kibanaVersion, - }) + this.options.logger.error( + `Error writing alert(${id}) to ${this.indexTemplateAndPattern.alias} - alert(${id}) doesn't exist in active alerts` ); } } @@ -360,34 +379,31 @@ export class AlertsClient< const alertsToIndex = [...activeAlertsToIndex, ...recoveredAlertsToIndex]; if (alertsToIndex.length > 0) { + const bulkBody = flatMap( + [...activeAlertsToIndex, ...recoveredAlertsToIndex].map((alert: Alert & AlertData) => [ + getBulkMeta( + alert.kibana.alert.uuid, + this.fetchedAlerts.indices[alert.kibana.alert.uuid], + this.fetchedAlerts.seqNo[alert.kibana.alert.uuid], + this.fetchedAlerts.primaryTerm[alert.kibana.alert.uuid], + this.isUsingDataStreams() + ), + alert, + ]) + ); + try { const response = await esClient.bulk({ refresh: 'wait_for', index: this.indexTemplateAndPattern.alias, - require_alias: true, - body: flatMap( - [...activeAlertsToIndex, ...recoveredAlertsToIndex].map((alert: Alert & AlertData) => [ - { - index: { - _id: alert.kibana.alert.uuid, - // If we know the concrete index for this alert, specify it - ...(this.fetchedAlerts.indices[alert.kibana.alert.uuid] - ? { - _index: this.fetchedAlerts.indices[alert.kibana.alert.uuid], - require_alias: false, - } - : {}), - }, - }, - alert, - ]) - ), + require_alias: !this.isUsingDataStreams(), + body: bulkBody, }); // If there were individual indexing errors, they will be returned in the success response if (response && response.errors) { const errorsInResponse = (response.items ?? []) - .map((item) => (item && item.index && item.index.error ? item.index.error : null)) + .map((item) => item?.index?.error || item?.create?.error) .filter((item) => item != null); this.options.logger.error( @@ -402,6 +418,33 @@ export class AlertsClient< ); } } + + function getBulkMeta( + uuid: string, + index: string | undefined, + seqNo: number | undefined, + primaryTerm: number | undefined, + isUsingDataStreams: boolean + ) { + if (index && seqNo != null && primaryTerm != null) { + return { + index: { + _id: uuid, + _index: index, + if_seq_no: seqNo, + if_primary_term: primaryTerm, + require_alias: false, + }, + }; + } + + return { + create: { + _id: uuid, + ...(isUsingDataStreams ? {} : { require_alias: true }), + }, + }; + } } public getAlertsToSerialize() { @@ -500,4 +543,8 @@ export class AlertsClient< }, }; } + + public isUsingDataStreams(): boolean { + return this._isUsingDataStreams; + } } diff --git a/x-pack/plugins/alerting/server/alerts_client/alerts_client_fixtures.ts b/x-pack/plugins/alerting/server/alerts_client/alerts_client_fixtures.ts index 4ff3c14120d14..aa513588b83f8 100644 --- a/x-pack/plugins/alerting/server/alerts_client/alerts_client_fixtures.ts +++ b/x-pack/plugins/alerting/server/alerts_client/alerts_client_fixtures.ts @@ -77,6 +77,7 @@ export const getParamsByTimeQuery: GetSummarizedAlertsParams = { }; export const getExpectedQueryByExecutionUuid = ({ + indexName, uuid = getParamsByExecutionUuid.executionUuid, ruleId = getParamsByExecutionUuid.ruleId, alertType, @@ -84,6 +85,7 @@ export const getExpectedQueryByExecutionUuid = ({ excludedAlertInstanceIds, alertsFilter, }: { + indexName: string; uuid?: string; ruleId?: string; alertType: keyof typeof alertTypes; @@ -184,10 +186,12 @@ export const getExpectedQueryByExecutionUuid = ({ size: 100, track_total_hits: true, }, - index: '.internal.alerts-test.alerts-default-*', + ignore_unavailable: true, + index: indexName, }); export const getExpectedQueryByTimeRange = ({ + indexName, end = getParamsByTimeQuery.end.toISOString(), start = getParamsByTimeQuery.start.toISOString(), ruleId = getParamsByTimeQuery.ruleId, @@ -196,6 +200,7 @@ export const getExpectedQueryByTimeRange = ({ excludedAlertInstanceIds, alertsFilter, }: { + indexName: string; end?: string; start?: string; ruleId?: string; @@ -344,6 +349,7 @@ export const getExpectedQueryByTimeRange = ({ size: 100, track_total_hits: true, }, - index: '.internal.alerts-test.alerts-default-*', + ignore_unavailable: true, + index: indexName, }; }; diff --git a/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.test.ts b/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.test.ts index 89f1a9469c2ea..f8c341e132e51 100644 --- a/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.test.ts +++ b/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.test.ts @@ -110,7 +110,7 @@ const testAlert2 = { meta: { lastScheduledActions: { group: 'default', - date: new Date(), + date: new Date().toISOString(), }, uuid: 'def', }, diff --git a/x-pack/plugins/alerting/server/alerts_service/alerts_service.test.ts b/x-pack/plugins/alerting/server/alerts_service/alerts_service.test.ts index e3942b26ee6fa..90552e1d5b0ac 100644 --- a/x-pack/plugins/alerting/server/alerts_service/alerts_service.test.ts +++ b/x-pack/plugins/alerting/server/alerts_service/alerts_service.test.ts @@ -7,6 +7,7 @@ import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { IndicesGetDataStreamResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { errors as EsErrors } from '@elastic/elasticsearch'; import { ReplaySubject, Subject } from 'rxjs'; import { AlertsService } from './alerts_service'; @@ -16,6 +17,7 @@ import { DEFAULT_NAMESPACE_STRING } from '@kbn/core-saved-objects-utils-server'; import { UntypedNormalizedRuleType } from '../rule_type_registry'; import { AlertsClient } from '../alerts_client'; import { alertsClientMock } from '../alerts_client/alerts_client.mock'; +import { getDataStreamAdapter } from './lib/data_stream_adapter'; jest.mock('../alerts_client'); @@ -63,6 +65,20 @@ const GetAliasResponse = { }, }; +const GetDataStreamResponse: IndicesGetDataStreamResponse = { + data_streams: [ + { + name: 'ignored', + generation: 1, + timestamp_field: { name: 'ignored' }, + hidden: true, + indices: [{ index_name: 'ignored', index_uuid: 'ignored' }], + status: 'green', + template: 'ignored', + }, + ], +}; + const IlmPutBody = { policy: { _meta: { @@ -88,6 +104,7 @@ interface GetIndexTemplatePutBodyOpts { useLegacyAlerts?: boolean; useEcs?: boolean; secondaryAlias?: string; + useDataStream?: boolean; } const getIndexTemplatePutBody = (opts?: GetIndexTemplatePutBodyOpts) => { const context = opts ? opts.context : undefined; @@ -95,25 +112,35 @@ const getIndexTemplatePutBody = (opts?: GetIndexTemplatePutBodyOpts) => { const useLegacyAlerts = opts ? opts.useLegacyAlerts : undefined; const useEcs = opts ? opts.useEcs : undefined; const secondaryAlias = opts ? opts.secondaryAlias : undefined; + const useDataStream = opts?.useDataStream ?? false; + + const indexPatterns = useDataStream + ? [`.alerts-${context ? context : 'test'}.alerts-${namespace}`] + : [`.internal.alerts-${context ? context : 'test'}.alerts-${namespace}-*`]; return { name: `.alerts-${context ? context : 'test'}.alerts-${namespace}-index-template`, body: { - index_patterns: [`.internal.alerts-${context ? context : 'test'}.alerts-${namespace}-*`], + index_patterns: indexPatterns, composed_of: [ ...(useEcs ? ['.alerts-ecs-mappings'] : []), `.alerts-${context ? `${context}.alerts` : 'test.alerts'}-mappings`, ...(useLegacyAlerts ? ['.alerts-legacy-alert-mappings'] : []), '.alerts-framework-mappings', ], + ...(useDataStream ? { data_stream: { hidden: true } } : {}), priority: namespace.length, template: { settings: { auto_expand_replicas: '0-1', hidden: true, - 'index.lifecycle': { - name: '.alerts-ilm-policy', - rollover_alias: `.alerts-${context ? context : 'test'}.alerts-${namespace}`, - }, + ...(useDataStream + ? {} + : { + 'index.lifecycle': { + name: '.alerts-ilm-policy', + rollover_alias: `.alerts-${context ? context : 'test'}.alerts-${namespace}`, + }, + }), 'index.mapping.total_fields.limit': 2500, }, mappings: { @@ -186,7 +213,7 @@ describe('Alerts Service', () => { let pluginStop$: Subject; beforeEach(() => { - jest.clearAllMocks(); + jest.resetAllMocks(); logger = loggingSystemMock.createLogger(); pluginStop$ = new ReplaySubject(1); jest.spyOn(global.Math, 'random').mockReturnValue(0.01); @@ -195,1809 +222,2145 @@ describe('Alerts Service', () => { async () => SimulateTemplateResponse ); clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); }); afterEach(() => { pluginStop$.next(); pluginStop$.complete(); }); - describe('AlertsService()', () => { - test('should correctly initialize common resources', async () => { - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - - expect(alertsService.isInitialized()).toEqual(true); - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(1); - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(3); - - const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); - const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; - expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); - const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; - expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); - }); - test('should log error and set initialized to false if adding ILM policy throws error', async () => { - clusterClient.ilm.putLifecycle.mockRejectedValueOnce(new Error('fail')); - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - - await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); + for (const useDataStreamForAlerts of [false, true]) { + const label = useDataStreamForAlerts ? 'data streams' : 'aliases'; + const dataStreamAdapter = getDataStreamAdapter({ useDataStreamForAlerts }); + + describe(`using ${label} for alert indices`, () => { + describe('AlertsService()', () => { + test('should correctly initialize common resources', async () => { + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + + expect(alertsService.isInitialized()).toEqual(true); + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + if (!useDataStreamForAlerts) { + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); + } + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(3); + + const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + }); - expect(alertsService.isInitialized()).toEqual(false); + test('should log error and set initialized to false if adding ILM policy throws error', async () => { + if (useDataStreamForAlerts) return; - expect(logger.error).toHaveBeenCalledWith( - `Error installing ILM policy .alerts-ilm-policy - fail` - ); + clusterClient.ilm.putLifecycle.mockRejectedValueOnce(new Error('fail')); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(1); - }); + await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); - test('should log error and set initialized to false if creating/updating common component template throws error', async () => { - clusterClient.cluster.putComponentTemplate.mockRejectedValueOnce(new Error('fail')); - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); + expect(alertsService.isInitialized()).toEqual(false); - await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); + expect(logger.error).toHaveBeenCalledWith( + `Error installing ILM policy .alerts-ilm-policy - fail` + ); - expect(alertsService.isInitialized()).toEqual(false); - expect(logger.error).toHaveBeenCalledWith( - `Error installing component template .alerts-framework-mappings - fail` - ); + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(1); + }); - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - }); + test('should log error and set initialized to false if creating/updating common component template throws error', async () => { + clusterClient.cluster.putComponentTemplate.mockRejectedValueOnce(new Error('fail')); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); + + expect(alertsService.isInitialized()).toEqual(false); + expect(logger.error).toHaveBeenCalledWith( + `Error installing component template .alerts-framework-mappings - fail` + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + }); - test('should update index template field limit and retry initialization if creating/updating common component template fails with field limit error', async () => { - clusterClient.cluster.putComponentTemplate.mockRejectedValueOnce( - new EsErrors.ResponseError( - elasticsearchClientMock.createApiResponse({ - statusCode: 400, - body: { - error: { - root_cause: [ - { + test('should update index template field limit and retry initialization if creating/updating common component template fails with field limit error', async () => { + clusterClient.cluster.putComponentTemplate.mockRejectedValueOnce( + new EsErrors.ResponseError( + elasticsearchClientMock.createApiResponse({ + statusCode: 400, + body: { + error: { + root_cause: [ + { + type: 'illegal_argument_exception', + reason: + 'updating component template [.alerts-ecs-mappings] results in invalid composable template [.alerts-security.alerts-default-index-template] after templates are merged', + }, + ], type: 'illegal_argument_exception', reason: 'updating component template [.alerts-ecs-mappings] results in invalid composable template [.alerts-security.alerts-default-index-template] after templates are merged', - }, - ], - type: 'illegal_argument_exception', - reason: - 'updating component template [.alerts-ecs-mappings] results in invalid composable template [.alerts-security.alerts-default-index-template] after templates are merged', - caused_by: { - type: 'illegal_argument_exception', - reason: - 'composable template [.alerts-security.alerts-default-index-template] template after composition with component templates [.alerts-ecs-mappings, .alerts-security.alerts-mappings, .alerts-technical-mappings] is invalid', - caused_by: { - type: 'illegal_argument_exception', - reason: - 'invalid composite mappings for [.alerts-security.alerts-default-index-template]', caused_by: { type: 'illegal_argument_exception', - reason: 'Limit of total fields [1900] has been exceeded', + reason: + 'composable template [.alerts-security.alerts-default-index-template] template after composition with component templates [.alerts-ecs-mappings, .alerts-security.alerts-mappings, .alerts-technical-mappings] is invalid', + caused_by: { + type: 'illegal_argument_exception', + reason: + 'invalid composite mappings for [.alerts-security.alerts-default-index-template]', + caused_by: { + type: 'illegal_argument_exception', + reason: 'Limit of total fields [1900] has been exceeded', + }, + }, }, }, }, + }) + ) + ); + const existingIndexTemplate = { + name: 'test-template', + index_template: { + index_patterns: ['test*'], + composed_of: ['.alerts-framework-mappings'], + template: { + settings: { + auto_expand_replicas: '0-1', + hidden: true, + 'index.lifecycle': { + name: '.alerts-ilm-policy', + rollover_alias: `.alerts-empty-default`, + }, + 'index.mapping.total_fields.limit': 1800, + }, + mappings: { + dynamic: false, + }, }, }, - }) - ) - ); - const existingIndexTemplate = { - name: 'test-template', - index_template: { - index_patterns: ['test*'], - composed_of: ['.alerts-framework-mappings'], - template: { - settings: { - auto_expand_replicas: '0-1', - hidden: true, - 'index.lifecycle': { - name: '.alerts-ilm-policy', - rollover_alias: `.alerts-empty-default`, + }; + clusterClient.indices.getIndexTemplate.mockResolvedValueOnce({ + index_templates: [existingIndexTemplate], + }); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + + expect(clusterClient.indices.getIndexTemplate).toHaveBeenCalledTimes(1); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(1); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({ + name: existingIndexTemplate.name, + body: { + ...existingIndexTemplate.index_template, + template: { + ...existingIndexTemplate.index_template.template, + settings: { + ...existingIndexTemplate.index_template.template?.settings, + 'index.mapping.total_fields.limit': 2500, + }, }, - 'index.mapping.total_fields.limit': 1800, - }, - mappings: { - dynamic: false, - }, - }, - }, - }; - clusterClient.indices.getIndexTemplate.mockResolvedValueOnce({ - index_templates: [existingIndexTemplate], - }); - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - - expect(clusterClient.indices.getIndexTemplate).toHaveBeenCalledTimes(1); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(1); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({ - name: existingIndexTemplate.name, - body: { - ...existingIndexTemplate.index_template, - template: { - ...existingIndexTemplate.index_template.template, - settings: { - ...existingIndexTemplate.index_template.template?.settings, - 'index.mapping.total_fields.limit': 2500, }, - }, - }, - }); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - // 3x for framework, legacy-alert and ecs mappings, then 1 extra time to update component template - // after updating index template field limit - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - }); - }); - - describe('register()', () => { - let alertsService: AlertsService; - beforeEach(async () => { - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', + }); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + // 3x for framework, legacy-alert and ecs mappings, then 1 extra time to update component template + // after updating index template field limit + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + }); }); - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - }); - - test('should correctly install resources for context when common initialization is complete', async () => { - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); - const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; - expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); - const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; - expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); - const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; - expect(componentTemplate4.name).toEqual('.alerts-test.alerts-mappings'); - - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( - getIndexTemplatePutBody() - ); - expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-*', - name: '.alerts-test.alerts-*', - }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, - }, - }, - }); - }); + describe('register()', () => { + let alertsService: AlertsService; + beforeEach(async () => { + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + }); - test('should correctly install resources for context when useLegacyAlerts is true', async () => { - alertsService.register({ ...TestRegistrationContext, useLegacyAlerts: true }); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); - const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; - expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); - const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; - expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); - const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; - expect(componentTemplate4.name).toEqual('.alerts-test.alerts-mappings'); - - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( - getIndexTemplatePutBody({ useLegacyAlerts: true }) - ); - expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-*', - name: '.alerts-test.alerts-*', - }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, - }, - }, - }); - }); + test('should correctly install resources for context when common initialization is complete', async () => { + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + if (!useDataStreamForAlerts) { + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); + } else { + expect(clusterClient.ilm.putLifecycle).not.toHaveBeenCalled(); + } + + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; + expect(componentTemplate4.name).toEqual('.alerts-test.alerts-mappings'); + + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( + getIndexTemplatePutBody({ useDataStream: useDataStreamForAlerts }) + ); + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalledWith({ + expand_wildcards: 'all', + name: '.alerts-test.alerts-default', + }); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-*', + name: '.alerts-test.alerts-*', + }); + } + }); - test('should correctly install resources for context when useEcs is true', async () => { - alertsService.register({ ...TestRegistrationContext, useEcs: true }); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); - const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; - expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); - const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; - expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); - const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; - expect(componentTemplate4.name).toEqual('.alerts-test.alerts-mappings'); - - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( - getIndexTemplatePutBody({ useEcs: true }) - ); - expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-*', - name: '.alerts-test.alerts-*', - }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, - }, - }, - }); - }); + test('should correctly install resources for context when useLegacyAlerts is true', async () => { + alertsService.register({ ...TestRegistrationContext, useLegacyAlerts: true }); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + if (!useDataStreamForAlerts) { + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); + } else { + expect(clusterClient.ilm.putLifecycle).not.toHaveBeenCalled(); + } + + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; + expect(componentTemplate4.name).toEqual('.alerts-test.alerts-mappings'); + + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( + getIndexTemplatePutBody({ + useLegacyAlerts: true, + useDataStream: useDataStreamForAlerts, + }) + ); + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalledWith({ + expand_wildcards: 'all', + name: '.alerts-test.alerts-default', + }); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-*', + name: '.alerts-test.alerts-*', + }); + } + }); - test('should correctly install resources for custom namespace on demand when isSpaceAware is true', async () => { - alertsService.register({ ...TestRegistrationContext, isSpaceAware: true }); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenNthCalledWith( - 1, - getIndexTemplatePutBody() - ); - expect(clusterClient.indices.getAlias).toHaveBeenNthCalledWith(1, { - index: '.internal.alerts-test.alerts-default-*', - name: '.alerts-test.alerts-*', - }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.create).toHaveBeenNthCalledWith(1, { - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, - }, - }, - }); + test('should correctly install resources for context when useEcs is true', async () => { + alertsService.register({ ...TestRegistrationContext, useEcs: true }); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + if (!useDataStreamForAlerts) { + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); + } else { + expect(clusterClient.ilm.putLifecycle).not.toHaveBeenCalled(); + } + + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; + expect(componentTemplate4.name).toEqual('.alerts-test.alerts-mappings'); + + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( + getIndexTemplatePutBody({ useEcs: true, useDataStream: useDataStreamForAlerts }) + ); + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenNthCalledWith(1, { + expand_wildcards: 'all', + name: '.alerts-test.alerts-default', + }); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-*', + name: '.alerts-test.alerts-*', + }); + } + }); - await retryUntil( - 'context in namespace initialized', - async () => - (await getContextInitialized( - alertsService, - TestRegistrationContext.context, - 'another-namespace' - )) === true - ); - - expect(clusterClient.indices.putIndexTemplate).toHaveBeenNthCalledWith( - 2, - getIndexTemplatePutBody({ namespace: 'another-namespace' }) - ); - expect(clusterClient.indices.getAlias).toHaveBeenNthCalledWith(2, { - index: '.internal.alerts-test.alerts-another-namespace-*', - name: '.alerts-test.alerts-*', - }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.create).toHaveBeenNthCalledWith(2, { - index: '.internal.alerts-test.alerts-another-namespace-000001', - body: { - aliases: { - '.alerts-test.alerts-another-namespace': { - is_write_index: true, - }, - }, - }, - }); - }); + test('should correctly install resources for custom namespace on demand when isSpaceAware is true', async () => { + alertsService.register({ ...TestRegistrationContext, isSpaceAware: true }); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + if (!useDataStreamForAlerts) { + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); + } else { + expect(clusterClient.ilm.putLifecycle).not.toHaveBeenCalled(); + } + + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenNthCalledWith( + 1, + getIndexTemplatePutBody({ useDataStream: useDataStreamForAlerts }) + ); + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenNthCalledWith(1, { + expand_wildcards: 'all', + name: '.alerts-test.alerts-default', + }); + } else { + expect(clusterClient.indices.create).toHaveBeenNthCalledWith(1, { + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + expect(clusterClient.indices.getAlias).toHaveBeenNthCalledWith(1, { + index: '.internal.alerts-test.alerts-default-*', + name: '.alerts-test.alerts-*', + }); + } + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + + clusterClient.indices.getDataStream.mockImplementationOnce(async () => ({ + data_streams: [], + })); + + await retryUntil( + 'context in namespace initialized', + async () => + (await getContextInitialized( + alertsService, + TestRegistrationContext.context, + 'another-namespace' + )) === true + ); + + expect(clusterClient.indices.putIndexTemplate).toHaveBeenNthCalledWith( + 2, + getIndexTemplatePutBody({ + namespace: 'another-namespace', + useDataStream: useDataStreamForAlerts, + }) + ); + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 4 + ); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 4 + ); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 4 + ); + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).toHaveBeenNthCalledWith(1, { + name: '.alerts-test.alerts-another-namespace', + }); + expect(clusterClient.indices.getDataStream).toHaveBeenNthCalledWith(2, { + expand_wildcards: 'all', + name: '.alerts-test.alerts-another-namespace', + }); + } else { + expect(clusterClient.indices.create).toHaveBeenNthCalledWith(2, { + index: '.internal.alerts-test.alerts-another-namespace-000001', + body: { + aliases: { + '.alerts-test.alerts-another-namespace': { + is_write_index: true, + }, + }, + }, + }); + expect(clusterClient.indices.getAlias).toHaveBeenNthCalledWith(2, { + index: '.internal.alerts-test.alerts-another-namespace-*', + name: '.alerts-test.alerts-*', + }); + } + }); - test('should correctly install resources for context when secondaryAlias is defined', async () => { - alertsService.register({ ...TestRegistrationContext, secondaryAlias: 'another.alias' }); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); - const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; - expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); - const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; - expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); - const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; - expect(componentTemplate4.name).toEqual('.alerts-test.alerts-mappings'); - - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( - getIndexTemplatePutBody({ secondaryAlias: 'another.alias' }) - ); - expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-*', - name: '.alerts-test.alerts-*', - }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, + test('should correctly install resources for context when secondaryAlias is defined', async () => { + if (useDataStreamForAlerts) return; + + alertsService.register({ ...TestRegistrationContext, secondaryAlias: 'another.alias' }); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); + + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; + expect(componentTemplate4.name).toEqual('.alerts-test.alerts-mappings'); + + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( + getIndexTemplatePutBody({ + secondaryAlias: 'another.alias', + useDataStream: useDataStreamForAlerts, + }) + ); + expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-*', + name: '.alerts-test.alerts-*', + }); + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, }, - }, - }, - }); - }); + }); + }); - test('should not install component template for context if fieldMap is empty', async () => { - alertsService.register({ - context: 'empty', - mappings: { fieldMap: {} }, - }); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService, 'empty')) === true - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(3); - const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); - const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; - expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); - const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; - expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); - - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({ - name: `.alerts-empty.alerts-default-index-template`, - body: { - index_patterns: [`.internal.alerts-empty.alerts-default-*`], - composed_of: ['.alerts-framework-mappings'], - priority: 7, - template: { - settings: { - auto_expand_replicas: '0-1', - hidden: true, - 'index.lifecycle': { - name: '.alerts-ilm-policy', - rollover_alias: `.alerts-empty.alerts-default`, + test('should not install component template for context if fieldMap is empty', async () => { + alertsService.register({ + context: 'empty', + mappings: { fieldMap: {} }, + }); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService, 'empty')) === true + ); + + if (!useDataStreamForAlerts) { + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); + } else { + expect(clusterClient.ilm.putLifecycle).not.toHaveBeenCalled(); + } + + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(3); + const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + + const template = { + name: `.alerts-empty.alerts-default-index-template`, + body: { + index_patterns: [ + useDataStreamForAlerts + ? `.alerts-empty.alerts-default` + : `.internal.alerts-empty.alerts-default-*`, + ], + composed_of: ['.alerts-framework-mappings'], + ...(useDataStreamForAlerts ? { data_stream: { hidden: true } } : {}), + priority: 7, + template: { + settings: { + auto_expand_replicas: '0-1', + hidden: true, + ...(useDataStreamForAlerts + ? {} + : { + 'index.lifecycle': { + name: '.alerts-ilm-policy', + rollover_alias: `.alerts-empty.alerts-default`, + }, + }), + 'index.mapping.total_fields.limit': 2500, + }, + mappings: { + _meta: { + kibana: { version: '8.8.0' }, + managed: true, + namespace: 'default', + }, + dynamic: false, + }, }, - 'index.mapping.total_fields.limit': 2500, - }, - mappings: { _meta: { kibana: { version: '8.8.0' }, managed: true, namespace: 'default', }, - dynamic: false, - }, - }, - _meta: { - kibana: { version: '8.8.0' }, - managed: true, - namespace: 'default', - }, - }, - }); - expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ - index: '.internal.alerts-empty.alerts-default-*', - name: '.alerts-empty.alerts-*', - }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-empty.alerts-default-000001', - body: { - aliases: { - '.alerts-empty.alerts-default': { - is_write_index: true, }, - }, - }, - }); - }); + }; + + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith(template); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalledWith({}); + expect(clusterClient.indices.getDataStream).toHaveBeenCalledWith({ + expand_wildcards: 'all', + name: '.alerts-empty.alerts-default', + }); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-empty.alerts-default-000001', + body: { + aliases: { + '.alerts-empty.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ + index: '.internal.alerts-empty.alerts-default-*', + name: '.alerts-empty.alerts-*', + }); + } + + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 1 : 2 + ); + }); - test('should skip initialization if context already exists', async () => { - alertsService.register(TestRegistrationContext); - alertsService.register(TestRegistrationContext); + test('should skip initialization if context already exists', async () => { + alertsService.register(TestRegistrationContext); + alertsService.register(TestRegistrationContext); - expect(logger.debug).toHaveBeenCalledWith( - `Resources for context "test" have already been registered.` - ); - }); + expect(logger.debug).toHaveBeenCalledWith( + `Resources for context "test" have already been registered.` + ); + }); - test('should throw error if context already exists and has been registered with a different field map', async () => { - alertsService.register(TestRegistrationContext); - expect(() => { - alertsService.register({ - ...TestRegistrationContext, - mappings: { fieldMap: { anotherField: { type: 'keyword', required: false } } }, + test('should throw error if context already exists and has been registered with a different field map', async () => { + alertsService.register(TestRegistrationContext); + expect(() => { + alertsService.register({ + ...TestRegistrationContext, + mappings: { fieldMap: { anotherField: { type: 'keyword', required: false } } }, + }); + }).toThrowErrorMatchingInlineSnapshot( + `"test has already been registered with different options"` + ); }); - }).toThrowErrorMatchingInlineSnapshot( - `"test has already been registered with different options"` - ); - }); - test('should throw error if context already exists and has been registered with a different options', async () => { - alertsService.register(TestRegistrationContext); - expect(() => { - alertsService.register({ - ...TestRegistrationContext, - useEcs: true, + test('should throw error if context already exists and has been registered with a different options', async () => { + alertsService.register(TestRegistrationContext); + expect(() => { + alertsService.register({ + ...TestRegistrationContext, + useEcs: true, + }); + }).toThrowErrorMatchingInlineSnapshot( + `"test has already been registered with different options"` + ); }); - }).toThrowErrorMatchingInlineSnapshot( - `"test has already been registered with different options"` - ); - }); - test('should not update index template if simulating template throws error', async () => { - clusterClient.indices.simulateTemplate.mockRejectedValueOnce(new Error('fail')); - - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(logger.error).toHaveBeenCalledWith( - `Failed to simulate index template mappings for .alerts-test.alerts-default-index-template; not applying mappings - fail` - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - // putIndexTemplate is skipped but other operations are called as expected - expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).toHaveBeenCalled(); - expect(clusterClient.indices.create).toHaveBeenCalled(); - }); + test('should not update index template if simulating template throws error', async () => { + clusterClient.indices.simulateTemplate.mockRejectedValueOnce(new Error('fail')); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + expect(logger.error).toHaveBeenCalledWith( + `Failed to simulate index template mappings for .alerts-test.alerts-default-index-template; not applying mappings - fail`, + expect.any(Error) + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + // putIndexTemplate is skipped but other operations are called as expected + expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + } + }); - test('should log error and set initialized to false if simulating template returns empty mappings', async () => { - clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => ({ - ...SimulateTemplateResponse, - template: { - ...SimulateTemplateResponse.template, - mappings: {}, - }, - })); - - alertsService.register(TestRegistrationContext); - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - expect( - await alertsService.getContextInitializationPromise( - TestRegistrationContext.context, - DEFAULT_NAMESPACE_STRING - ) - ).toEqual({ - result: false, - error: - 'Failure during installation. No mappings would be generated for .alerts-test.alerts-default-index-template, possibly due to failed/misconfigured bootstrapping', - }); + test('should log error and set initialized to false if simulating template returns empty mappings', async () => { + clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => ({ + ...SimulateTemplateResponse, + template: { + ...SimulateTemplateResponse.template, + mappings: {}, + }, + })); + + alertsService.register(TestRegistrationContext); + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + expect( + await alertsService.getContextInitializationPromise( + TestRegistrationContext.context, + DEFAULT_NAMESPACE_STRING + ) + ).toEqual({ + result: false, + error: + 'Failure during installation. No mappings would be generated for .alerts-test.alerts-default-index-template, possibly due to failed/misconfigured bootstrapping', + }); + + expect(logger.error).toHaveBeenCalledWith( + new Error( + `No mappings would be generated for .alerts-test.alerts-default-index-template, possibly due to failed/misconfigured bootstrapping` + ) + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + }); - expect(logger.error).toHaveBeenCalledWith( - new Error( - `No mappings would be generated for .alerts-test.alerts-default-index-template, possibly due to failed/misconfigured bootstrapping` - ) - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - }); + test('should log error and set initialized to false if updating index template throws error', async () => { + clusterClient.indices.putIndexTemplate.mockRejectedValueOnce(new Error('fail')); + + alertsService.register(TestRegistrationContext); + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + + expect( + await alertsService.getContextInitializationPromise( + TestRegistrationContext.context, + DEFAULT_NAMESPACE_STRING + ) + ).toEqual({ error: 'Failure during installation. fail', result: false }); + + expect(logger.error).toHaveBeenCalledWith( + `Error installing index template .alerts-test.alerts-default-index-template - fail`, + expect.any(Error) + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + }); - test('should log error and set initialized to false if updating index template throws error', async () => { - clusterClient.indices.putIndexTemplate.mockRejectedValueOnce(new Error('fail')); - - alertsService.register(TestRegistrationContext); - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - - expect( - await alertsService.getContextInitializationPromise( - TestRegistrationContext.context, - DEFAULT_NAMESPACE_STRING - ) - ).toEqual({ error: 'Failure during installation. fail', result: false }); - - expect(logger.error).toHaveBeenCalledWith( - `Error installing index template .alerts-test.alerts-default-index-template - fail` - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - }); + test('should log error and set initialized to false if checking for concrete write index throws error', async () => { + clusterClient.indices.getAlias.mockRejectedValueOnce(new Error('fail')); + clusterClient.indices.getDataStream.mockRejectedValueOnce(new Error('fail')); + + alertsService.register(TestRegistrationContext); + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + expect( + await alertsService.getContextInitializationPromise( + TestRegistrationContext.context, + DEFAULT_NAMESPACE_STRING + ) + ).toEqual({ error: 'Failure during installation. fail', result: false }); + + expect(logger.error).toHaveBeenCalledWith( + useDataStreamForAlerts + ? `Error fetching data stream for .alerts-test.alerts-default - fail` + : `Error fetching concrete indices for .internal.alerts-test.alerts-default-* pattern - fail` + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + }); - test('should log error and set initialized to false if checking for concrete write index throws error', async () => { - clusterClient.indices.getAlias.mockRejectedValueOnce(new Error('fail')); - - alertsService.register(TestRegistrationContext); - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - expect( - await alertsService.getContextInitializationPromise( - TestRegistrationContext.context, - DEFAULT_NAMESPACE_STRING - ) - ).toEqual({ error: 'Failure during installation. fail', result: false }); - - expect(logger.error).toHaveBeenCalledWith( - `Error fetching concrete indices for .internal.alerts-test.alerts-default-* pattern - fail` - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - }); + test('should not throw error if checking for concrete write index throws 404', async () => { + const error = new Error(`index doesn't exist`) as HTTPError; + error.statusCode = 404; + clusterClient.indices.getAlias.mockRejectedValueOnce(error); + clusterClient.indices.getDataStream.mockRejectedValueOnce(error); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).toHaveBeenCalled(); + } + }); - test('should not throw error if checking for concrete write index throws 404', async () => { - const error = new Error(`index doesn't exist`) as HTTPError; - error.statusCode = 404; - clusterClient.indices.getAlias.mockRejectedValueOnce(error); - - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).toHaveBeenCalled(); - }); + test('should log error and set initialized to false if updating index settings for existing indices throws error', async () => { + clusterClient.indices.putSettings.mockRejectedValueOnce(new Error('fail')); + + alertsService.register(TestRegistrationContext); + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + + expect( + await alertsService.getContextInitializationPromise( + TestRegistrationContext.context, + DEFAULT_NAMESPACE_STRING + ) + ).toEqual({ error: 'Failure during installation. fail', result: false }); + + expect(logger.error).toHaveBeenCalledWith( + useDataStreamForAlerts + ? `Failed to PUT index.mapping.total_fields.limit settings for .alerts-test.alerts-default: fail` + : `Failed to PUT index.mapping.total_fields.limit settings for alias_1: fail` + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + } + }); - test('should log error and set initialized to false if updating index settings for existing indices throws error', async () => { - clusterClient.indices.putSettings.mockRejectedValueOnce(new Error('fail')); - - alertsService.register(TestRegistrationContext); - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - - expect( - await alertsService.getContextInitializationPromise( - TestRegistrationContext.context, - DEFAULT_NAMESPACE_STRING - ) - ).toEqual({ error: 'Failure during installation. fail', result: false }); - - expect(logger.error).toHaveBeenCalledWith( - `Failed to PUT index.mapping.total_fields.limit settings for alias alias_1: fail` - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - }); + test('should skip updating index mapping for existing indices if simulate index template throws error', async () => { + clusterClient.indices.simulateIndexTemplate.mockRejectedValueOnce(new Error('fail')); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + expect(logger.error).toHaveBeenCalledWith( + useDataStreamForAlerts + ? `Ignored PUT mappings for .alerts-test.alerts-default; error generating simulated mappings: fail` + : `Ignored PUT mappings for alias_1; error generating simulated mappings: fail` + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + + // this is called to update backing indices, so not used with data streams + expect(clusterClient.indices.putMapping).toHaveBeenCalled(); + } + }); - test('should skip updating index mapping for existing indices if simulate index template throws error', async () => { - clusterClient.indices.simulateIndexTemplate.mockRejectedValueOnce(new Error('fail')); - - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(logger.error).toHaveBeenCalledWith( - `Ignored PUT mappings for alias alias_1; error generating simulated mappings: fail` - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).toHaveBeenCalled(); - expect(clusterClient.indices.create).toHaveBeenCalled(); - }); + test('should log error and set initialized to false if updating index mappings for existing indices throws error', async () => { + clusterClient.indices.putMapping.mockRejectedValueOnce(new Error('fail')); + + alertsService.register(TestRegistrationContext); + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + expect( + await alertsService.getContextInitializationPromise( + TestRegistrationContext.context, + DEFAULT_NAMESPACE_STRING + ) + ).toEqual({ error: 'Failure during installation. fail', result: false }); + + if (useDataStreamForAlerts) { + expect(logger.error).toHaveBeenCalledWith( + `Failed to PUT mapping for .alerts-test.alerts-default: fail` + ); + } else { + expect(logger.error).toHaveBeenCalledWith(`Failed to PUT mapping for alias_1: fail`); + } + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + } + }); - test('should log error and set initialized to false if updating index mappings for existing indices throws error', async () => { - clusterClient.indices.putMapping.mockRejectedValueOnce(new Error('fail')); - - alertsService.register(TestRegistrationContext); - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - expect( - await alertsService.getContextInitializationPromise( - TestRegistrationContext.context, - DEFAULT_NAMESPACE_STRING - ) - ).toEqual({ error: 'Failure during installation. fail', result: false }); - - expect(logger.error).toHaveBeenCalledWith(`Failed to PUT mapping for alias alias_1: fail`); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - }); + test('does not updating settings or mappings if no existing concrete indices', async () => { + clusterClient.indices.getAlias.mockImplementationOnce(async () => ({})); + clusterClient.indices.getDataStream.mockImplementationOnce(async () => ({ + data_streams: [], + })); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + } + }); - test('does not updating settings or mappings if no existing concrete indices', async () => { - clusterClient.indices.getAlias.mockImplementationOnce(async () => ({})); - - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).toHaveBeenCalled(); - }); + test('should log error and set initialized to false if concrete indices exist but none are write index', async () => { + // not applicable for data streams + if (useDataStreamForAlerts) return; - test('should log error and set initialized to false if concrete indices exist but none are write index', async () => { - clusterClient.indices.getAlias.mockImplementationOnce(async () => ({ - '.internal.alerts-test.alerts-default-0001': { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: false, - is_hidden: true, - }, - alias_2: { - is_write_index: false, - is_hidden: true, + clusterClient.indices.getAlias.mockImplementationOnce(async () => ({ + '.internal.alerts-test.alerts-default-0001': { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: false, + is_hidden: true, + }, + alias_2: { + is_write_index: false, + is_hidden: true, + }, + }, }, - }, - }, - })); - - alertsService.register(TestRegistrationContext); - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - expect( - await alertsService.getContextInitializationPromise( - TestRegistrationContext.context, - DEFAULT_NAMESPACE_STRING - ) - ).toEqual({ - error: - 'Failure during installation. Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default', - result: false, - }); + })); + + alertsService.register(TestRegistrationContext); + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + expect( + await alertsService.getContextInitializationPromise( + TestRegistrationContext.context, + DEFAULT_NAMESPACE_STRING + ) + ).toEqual({ + error: + 'Failure during installation. Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default', + result: false, + }); + + expect(logger.error).toHaveBeenCalledWith( + new Error( + `Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default` + ) + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + }); - expect(logger.error).toHaveBeenCalledWith( - new Error( - `Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default` - ) - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - }); + test('does not create new index if concrete write index exists', async () => { + // not applicable for data streams + if (useDataStreamForAlerts) return; - test('does not create new index if concrete write index exists', async () => { - clusterClient.indices.getAlias.mockImplementationOnce(async () => ({ - '.internal.alerts-test.alerts-default-0001': { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - is_hidden: true, - }, - alias_2: { - is_write_index: false, - is_hidden: true, + clusterClient.indices.getAlias.mockImplementationOnce(async () => ({ + '.internal.alerts-test.alerts-default-0001': { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + is_hidden: true, + }, + alias_2: { + is_write_index: false, + is_hidden: true, + }, + }, }, - }, - }, - })); - - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - }); - - test('should log error and set initialized to false if create concrete index throws error', async () => { - clusterClient.indices.create.mockRejectedValueOnce(new Error('fail')); - - alertsService.register(TestRegistrationContext); - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - - expect( - await alertsService.getContextInitializationPromise( - TestRegistrationContext.context, - DEFAULT_NAMESPACE_STRING - ) - ).toEqual({ error: 'Failure during installation. fail', result: false }); - - expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).toHaveBeenCalled(); - expect(clusterClient.indices.create).toHaveBeenCalled(); - }); - - test('should not throw error if create concrete index throws resource_already_exists_exception error and write index already exists', async () => { - const error = new Error(`fail`) as EsError; - error.meta = { - body: { - error: { - type: 'resource_already_exists_exception', - }, - }, - }; - clusterClient.indices.create.mockRejectedValueOnce(error); - clusterClient.indices.get.mockImplementationOnce(async () => ({ - '.internal.alerts-test.alerts-default-000001': { - aliases: { '.alerts-test.alerts-default': { is_write_index: true } }, - }, - })); - - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).toHaveBeenCalled(); - expect(clusterClient.indices.get).toHaveBeenCalled(); - expect(clusterClient.indices.create).toHaveBeenCalled(); - }); - - test('should log error and set initialized to false if create concrete index throws resource_already_exists_exception error and write index does not already exists', async () => { - const error = new Error(`fail`) as EsError; - error.meta = { - body: { - error: { - type: 'resource_already_exists_exception', - }, - }, - }; - clusterClient.indices.create.mockRejectedValueOnce(error); - clusterClient.indices.get.mockImplementationOnce(async () => ({ - '.internal.alerts-test.alerts-default-000001': { - aliases: { '.alerts-test.alerts-default': { is_write_index: false } }, - }, - })); - - alertsService.register(TestRegistrationContext); - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - expect( - await alertsService.getContextInitializationPromise( - TestRegistrationContext.context, - DEFAULT_NAMESPACE_STRING - ) - ).toEqual({ - error: - 'Failure during installation. Attempted to create index: .internal.alerts-test.alerts-default-000001 as the write index for alias: .alerts-test.alerts-default, but the index already exists and is not the write index for the alias', - result: false, - }); - - expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); - expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.putMapping).toHaveBeenCalled(); - expect(clusterClient.indices.get).toHaveBeenCalled(); - expect(clusterClient.indices.create).toHaveBeenCalled(); - }); - }); - - describe('createAlertsClient()', () => { - let alertsService: AlertsService; - beforeEach(async () => { - (AlertsClient as jest.Mock).mockImplementation(() => alertsClient); - }); - - test('should create new AlertsClient', async () => { - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - await alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - }); - - expect(AlertsClient).toHaveBeenCalledWith({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - kibanaVersion: '8.8.0', - }); - }); - - test('should return null if rule type has no alert definition', async () => { - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - const result = await alertsService.createAlertsClient({ - logger, - ruleType, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - }); - - expect(result).toBe(null); - expect(AlertsClient).not.toHaveBeenCalled(); - }); - - test('should retry initializing common resources if common resource initialization failed', async () => { - clusterClient.ilm.putLifecycle.mockRejectedValueOnce(new Error('fail')); - - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - alertsService.register(TestRegistrationContext); - - await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); - - expect(alertsService.isInitialized()).toEqual(false); - - // Installing ILM policy failed so no calls to install context-specific resources - // should be made - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(1); - expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - - const result = await alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - }); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.create).toHaveBeenCalled(); - - expect(AlertsClient).toHaveBeenCalledWith({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - kibanaVersion: '8.8.0', - }); - - expect(result).not.toBe(null); - expect(logger.info).toHaveBeenCalledWith(`Retrying common resource initialization`); - expect(logger.info).toHaveBeenCalledWith( - `Retrying resource initialization for context "test"` - ); - expect(logger.info).toHaveBeenCalledWith( - `Resource installation for "test" succeeded after retry` - ); - }); + })); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + } + }); - test('should not retry initializing common resources if common resource initialization is in progress', async () => { - // this is the initial call that fails - clusterClient.ilm.putLifecycle.mockRejectedValueOnce(new Error('fail')); + test('should log error and set initialized to false if create concrete index throws error', async () => { + // not applicable for data streams + if (useDataStreamForAlerts) return; + + clusterClient.indices.create.mockRejectedValueOnce(new Error('fail')); + clusterClient.indices.createDataStream.mockRejectedValueOnce(new Error('fail')); + + alertsService.register(TestRegistrationContext); + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + + expect( + await alertsService.getContextInitializationPromise( + TestRegistrationContext.context, + DEFAULT_NAMESPACE_STRING + ) + ).toEqual({ error: 'Failure during installation. fail', result: false }); + + expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + } + }); - // this is the retry call that we'll artificially inflate the duration of - clusterClient.ilm.putLifecycle.mockImplementationOnce(async () => { - await new Promise((r) => setTimeout(r, 1000)); - return { acknowledged: true }; - }); + test('should not throw error if create concrete index throws resource_already_exists_exception error and write index already exists', async () => { + // not applicable for data streams + if (useDataStreamForAlerts) return; - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - alertsService.register(TestRegistrationContext); - - await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); - - expect(alertsService.isInitialized()).toEqual(false); - - // Installing ILM policy failed so no calls to install context-specific resources - // should be made - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(1); - expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - - // call createAlertsClient at the same time which will trigger the retries - const result = await Promise.all([ - alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, + const error = new Error(`fail`) as EsError; + error.meta = { + body: { + error: { + type: 'resource_already_exists_exception', + }, }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - }), - alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, + }; + clusterClient.indices.create.mockRejectedValueOnce(error); + clusterClient.indices.get.mockImplementationOnce(async () => ({ + '.internal.alerts-test.alerts-default-000001': { + aliases: { '.alerts-test.alerts-default': { is_write_index: true } }, }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - }), - ]); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).toHaveBeenCalled(); - expect(clusterClient.indices.create).toHaveBeenCalled(); - - expect(AlertsClient).toHaveBeenCalledWith({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - kibanaVersion: '8.8.0', - }); - - expect(result[0]).not.toBe(null); - expect(result[1]).not.toBe(null); - expect(logger.info).toHaveBeenCalledWith(`Retrying common resource initialization`); - expect(logger.info).toHaveBeenCalledWith( - `Retrying resource initialization for context "test"` - ); - expect(logger.info).toHaveBeenCalledWith( - `Resource installation for "test" succeeded after retry` - ); - expect(logger.info).toHaveBeenCalledWith( - `Skipped retrying common resource initialization because it is already being retried.` - ); - }); - - test('should retry initializing context specific resources if context specific resource initialization failed', async () => { - clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => ({ - ...SimulateTemplateResponse, - template: { - ...SimulateTemplateResponse.template, - mappings: {}, - }, - })); - - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - alertsService.register(TestRegistrationContext); - - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - - const result = await alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - }); - - expect(AlertsClient).toHaveBeenCalledWith({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - kibanaVersion: '8.8.0', - }); - - expect(result).not.toBe(null); - expect(logger.info).not.toHaveBeenCalledWith(`Retrying common resource initialization`); - expect(logger.info).toHaveBeenCalledWith( - `Retrying resource initialization for context "test"` - ); - expect(logger.info).toHaveBeenCalledWith( - `Resource installation for "test" succeeded after retry` - ); - }); - - test('should not retry initializing context specific resources if context specific resource initialization is in progress', async () => { - // this is the initial call that fails - clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => ({ - ...SimulateTemplateResponse, - template: { - ...SimulateTemplateResponse.template, - mappings: {}, - }, - })); + })); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).toHaveBeenCalled(); + expect(clusterClient.indices.get).toHaveBeenCalled(); + expect(clusterClient.indices.create).toHaveBeenCalled(); + }); - // this is the retry call that we'll artificially inflate the duration of - clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => { - await new Promise((r) => setTimeout(r, 1000)); - return SimulateTemplateResponse; - }); + test('should log error and set initialized to false if create concrete index throws resource_already_exists_exception error and write index does not already exists', async () => { + // not applicable for data streams + if (useDataStreamForAlerts) return; - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - alertsService.register(TestRegistrationContext); - - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - - const createAlertsClientWithDelay = async (delayMs: number | null) => { - if (delayMs) { - await new Promise((r) => setTimeout(r, delayMs)); - } - - return await alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, + const error = new Error(`fail`) as EsError; + error.meta = { + body: { + error: { + type: 'resource_already_exists_exception', + }, }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, + }; + clusterClient.indices.create.mockRejectedValueOnce(error); + clusterClient.indices.get.mockImplementationOnce(async () => ({ + '.internal.alerts-test.alerts-default-000001': { + aliases: { '.alerts-test.alerts-default': { is_write_index: false } }, + }, + })); + + alertsService.register(TestRegistrationContext); + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + expect( + await alertsService.getContextInitializationPromise( + TestRegistrationContext.context, + DEFAULT_NAMESPACE_STRING + ) + ).toEqual({ + error: + 'Failure during installation. Attempted to create index: .internal.alerts-test.alerts-default-000001 as the write index for alias: .alerts-test.alerts-default, but the index already exists and is not the write index for the alias', + result: false, + }); + + expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putMapping).toHaveBeenCalled(); + expect(clusterClient.indices.get).toHaveBeenCalled(); + expect(clusterClient.indices.create).toHaveBeenCalled(); }); - }; - - const result = await Promise.all([ - createAlertsClientWithDelay(null), - createAlertsClientWithDelay(1), - ]); - - expect(AlertsClient).toHaveBeenCalledTimes(2); - expect(AlertsClient).toHaveBeenCalledWith({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - kibanaVersion: '8.8.0', }); - expect(result[0]).not.toBe(null); - expect(result[1]).not.toBe(null); - expect(logger.info).not.toHaveBeenCalledWith(`Retrying common resource initialization`); - - // Should only log the retry once because the second call should - // leverage the outcome of the first retry - expect( - logger.info.mock.calls.filter( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (calls: any[]) => calls[0] === `Retrying resource initialization for context "test"` - ).length - ).toEqual(1); - expect( - logger.info.mock.calls.filter( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (calls: any[]) => calls[0] === `Resource installation for "test" succeeded after retry` - ).length - ).toEqual(1); - }); + describe('createAlertsClient()', () => { + let alertsService: AlertsService; + beforeEach(async () => { + (AlertsClient as jest.Mock).mockImplementation(() => alertsClient); + }); - test('should throttle retries of initializing context specific resources', async () => { - // this is the initial call that fails - clusterClient.indices.simulateTemplate.mockImplementation(async () => ({ - ...SimulateTemplateResponse, - template: { - ...SimulateTemplateResponse.template, - mappings: {}, - }, - })); + test('should create new AlertsClient', async () => { + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + await alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - alertsService.register(TestRegistrationContext); - - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - - const createAlertsClientWithDelay = async (delayMs: number | null) => { - if (delayMs) { - await new Promise((r) => setTimeout(r, delayMs)); - } - - return await alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, + expect(AlertsClient).toHaveBeenCalledWith({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + dataStreamAdapter, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, + kibanaVersion: '8.8.0', + }); }); - }; - - await Promise.all([ - createAlertsClientWithDelay(null), - createAlertsClientWithDelay(1), - createAlertsClientWithDelay(2), - ]); - - expect(logger.info).not.toHaveBeenCalledWith(`Retrying common resource initialization`); - - // Should only log the retry once because the second and third retries should be throttled - expect( - logger.info.mock.calls.filter( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (calls: any[]) => calls[0] === `Retrying resource initialization for context "test"` - ).length - ).toEqual(1); - }); - - test('should return null if retrying common resources initialization fails again', async () => { - clusterClient.ilm.putLifecycle.mockRejectedValueOnce(new Error('fail')); - clusterClient.ilm.putLifecycle.mockRejectedValueOnce(new Error('fail again')); - - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - alertsService.register(TestRegistrationContext); - - await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); - - expect(alertsService.isInitialized()).toEqual(false); - - // Installing ILM policy failed so no calls to install context-specific resources - // should be made - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(1); - expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - - const result = await alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - }); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - - expect(result).toBe(null); - expect(AlertsClient).not.toHaveBeenCalled(); - expect(logger.info).toHaveBeenCalledWith(`Retrying common resource initialization`); - expect(logger.info).toHaveBeenCalledWith( - `Retrying resource initialization for context "test"` - ); - expect(logger.warn).toHaveBeenCalledWith( - `There was an error in the framework installing namespace-level resources and creating concrete indices for context "test" - Original error: Failure during installation. fail; Error after retry: Failure during installation. fail again` - ); - }); - - test('should return null if retrying common resources initialization fails again with same error', async () => { - clusterClient.ilm.putLifecycle.mockRejectedValueOnce(new Error('fail')); - clusterClient.ilm.putLifecycle.mockRejectedValueOnce(new Error('fail')); - - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - alertsService.register(TestRegistrationContext); - - await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); - - expect(alertsService.isInitialized()).toEqual(false); - - // Installing ILM policy failed so no calls to install context-specific resources - // should be made - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(1); - expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - - const result = await alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - }); - - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); - expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); - expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); - expect(clusterClient.indices.create).not.toHaveBeenCalled(); - - expect(result).toBe(null); - expect(AlertsClient).not.toHaveBeenCalled(); - expect(logger.info).toHaveBeenCalledWith(`Retrying common resource initialization`); - expect(logger.info).toHaveBeenCalledWith( - `Retrying resource initialization for context "test"` - ); - expect(logger.warn).toHaveBeenCalledWith( - `There was an error in the framework installing namespace-level resources and creating concrete indices for context "test" - Retry failed with error: Failure during installation. fail` - ); - }); - - test('should return null if retrying context specific initialization fails again', async () => { - clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => ({ - ...SimulateTemplateResponse, - template: { - ...SimulateTemplateResponse.template, - mappings: {}, - }, - })); - clusterClient.indices.putIndexTemplate.mockRejectedValueOnce( - new Error('fail index template') - ); - - alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); - alertsService.register(TestRegistrationContext); - - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - - const result = await alertsService.createAlertsClient({ - logger, - ruleType: ruleTypeWithAlertDefinition, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, - }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], - }, - }); - expect(AlertsClient).not.toHaveBeenCalled(); - expect(result).toBe(null); - expect(logger.info).not.toHaveBeenCalledWith(`Retrying common resource initialization`); - expect(logger.info).toHaveBeenCalledWith( - `Retrying resource initialization for context "test"` - ); - expect(logger.warn).toHaveBeenCalledWith( - `There was an error in the framework installing namespace-level resources and creating concrete indices for context "test" - Original error: Failure during installation. No mappings would be generated for .alerts-test.alerts-default-index-template, possibly due to failed/misconfigured bootstrapping; Error after retry: Failure during installation. fail index template` - ); - }); - }); - - describe('retries', () => { - test('should retry adding ILM policy for transient ES errors', async () => { - clusterClient.ilm.putLifecycle - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockResolvedValue({ acknowledged: true }); - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); + test('should return null if rule type has no alert definition', async () => { + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + const result = await alertsService.createAlertsClient({ + logger, + ruleType, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(3); - }); + expect(result).toBe(null); + expect(AlertsClient).not.toHaveBeenCalled(); + }); - test('should retry adding component template for transient ES errors', async () => { - clusterClient.cluster.putComponentTemplate - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockResolvedValue({ acknowledged: true }); - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); + test('should retry initializing common resources if common resource initialization failed', async () => { + clusterClient.cluster.putComponentTemplate.mockRejectedValueOnce(new Error('fail')); + + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + alertsService.register(TestRegistrationContext); + + await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); + + expect(alertsService.isInitialized()).toEqual(false); + + // Installing ILM policy failed so no calls to install context-specific resources + // should be made + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + + const result = await alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 2 + ); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + } + + expect(AlertsClient).toHaveBeenCalledWith({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + dataStreamAdapter, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + kibanaVersion: '8.8.0', + }); + + expect(result).not.toBe(null); + expect(logger.info).toHaveBeenCalledWith(`Retrying common resource initialization`); + expect(logger.info).toHaveBeenCalledWith( + `Retrying resource initialization for context "test"` + ); + expect(logger.info).toHaveBeenCalledWith( + `Resource installation for "test" succeeded after retry` + ); + }); - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(5); - }); + test('should not retry initializing common resources if common resource initialization is in progress', async () => { + // this is the initial call that fails + clusterClient.cluster.putComponentTemplate.mockRejectedValueOnce(new Error('fail')); + + // this is the retry call that we'll artificially inflate the duration of + clusterClient.cluster.putComponentTemplate.mockImplementationOnce(async () => { + await new Promise((r) => setTimeout(r, 1000)); + return { acknowledged: true }; + }); + + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + alertsService.register(TestRegistrationContext); + + await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); + + expect(alertsService.isInitialized()).toEqual(false); + + // Installing ILM policy failed so no calls to install context-specific resources + // should be made + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + + // call createAlertsClient at the same time which will trigger the retries + const result = await Promise.all([ + alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }), + alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }), + ]); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 2 + ); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).toHaveBeenCalled(); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + expect(clusterClient.indices.getDataStream).toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).toHaveBeenCalled(); + } + expect(AlertsClient).toHaveBeenCalledWith({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + dataStreamAdapter, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + kibanaVersion: '8.8.0', + }); + + expect(result[0]).not.toBe(null); + expect(result[1]).not.toBe(null); + expect(logger.info).toHaveBeenCalledWith(`Retrying common resource initialization`); + expect(logger.info).toHaveBeenCalledWith( + `Retrying resource initialization for context "test"` + ); + expect(logger.info).toHaveBeenCalledWith( + `Resource installation for "test" succeeded after retry` + ); + expect(logger.info).toHaveBeenCalledWith( + `Skipped retrying common resource initialization because it is already being retried.` + ); + }); - test('should retry updating index template for transient ES errors', async () => { - clusterClient.indices.putIndexTemplate - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockResolvedValue({ acknowledged: true }); - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); + test('should retry initializing context specific resources if context specific resource initialization failed', async () => { + clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => ({ + ...SimulateTemplateResponse, + template: { + ...SimulateTemplateResponse.template, + mappings: {}, + }, + })); + + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + alertsService.register(TestRegistrationContext); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + + const result = await alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - expect(alertsService.isInitialized()).toEqual(true); + expect(AlertsClient).toHaveBeenCalledWith({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + dataStreamAdapter, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + kibanaVersion: '8.8.0', + }); + + expect(result).not.toBe(null); + expect(logger.info).not.toHaveBeenCalledWith(`Retrying common resource initialization`); + expect(logger.info).toHaveBeenCalledWith( + `Retrying resource initialization for context "test"` + ); + expect(logger.info).toHaveBeenCalledWith( + `Resource installation for "test" succeeded after retry` + ); + }); - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); + test('should not retry initializing context specific resources if context specific resource initialization is in progress', async () => { + // this is the initial call that fails + clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => ({ + ...SimulateTemplateResponse, + template: { + ...SimulateTemplateResponse.template, + mappings: {}, + }, + })); + + // this is the retry call that we'll artificially inflate the duration of + clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => { + await new Promise((r) => setTimeout(r, 1000)); + return SimulateTemplateResponse; + }); + + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + alertsService.register(TestRegistrationContext); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + + const createAlertsClientWithDelay = async (delayMs: number | null) => { + if (delayMs) { + await new Promise((r) => setTimeout(r, delayMs)); + } - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(3); - }); + return await alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); + }; + + const result = await Promise.all([ + createAlertsClientWithDelay(null), + createAlertsClientWithDelay(1), + ]); + + expect(AlertsClient).toHaveBeenCalledTimes(2); + expect(AlertsClient).toHaveBeenCalledWith({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + dataStreamAdapter, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + kibanaVersion: '8.8.0', + }); + + expect(result[0]).not.toBe(null); + expect(result[1]).not.toBe(null); + expect(logger.info).not.toHaveBeenCalledWith(`Retrying common resource initialization`); + + // Should only log the retry once because the second call should + // leverage the outcome of the first retry + expect( + logger.info.mock.calls.filter( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (calls: any[]) => calls[0] === `Retrying resource initialization for context "test"` + ).length + ).toEqual(1); + expect( + logger.info.mock.calls.filter( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (calls: any[]) => + calls[0] === `Resource installation for "test" succeeded after retry` + ).length + ).toEqual(1); + }); - test('should retry updating index settings for existing indices for transient ES errors', async () => { - clusterClient.indices.putSettings - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockResolvedValue({ acknowledged: true }); - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); + test('should throttle retries of initializing context specific resources', async () => { + // this is the initial call that fails + clusterClient.indices.simulateTemplate.mockImplementation(async () => ({ + ...SimulateTemplateResponse, + template: { + ...SimulateTemplateResponse.template, + mappings: {}, + }, + })); + + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + alertsService.register(TestRegistrationContext); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + + const createAlertsClientWithDelay = async (delayMs: number | null) => { + if (delayMs) { + await new Promise((r) => setTimeout(r, delayMs)); + } - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); + return await alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); + }; + + await Promise.all([ + createAlertsClientWithDelay(null), + createAlertsClientWithDelay(1), + createAlertsClientWithDelay(2), + ]); + + expect(logger.info).not.toHaveBeenCalledWith(`Retrying common resource initialization`); + + // Should only log the retry once because the second and third retries should be throttled + expect( + logger.info.mock.calls.filter( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (calls: any[]) => calls[0] === `Retrying resource initialization for context "test"` + ).length + ).toEqual(1); + }); - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); + test('should return null if retrying common resources initialization fails again', async () => { + let failCount = 0; + clusterClient.cluster.putComponentTemplate.mockImplementation(() => { + throw new Error(`fail ${++failCount}`); + }); + + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + alertsService.register(TestRegistrationContext); + + await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); + + expect(alertsService.isInitialized()).toEqual(false); + + // Installing ILM policy failed so no calls to install context-specific resources + // should be made + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + + const result = await alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 2 + ); + expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + + expect(result).toBe(null); + expect(AlertsClient).not.toHaveBeenCalled(); + expect(logger.info).toHaveBeenCalledWith(`Retrying common resource initialization`); + expect(logger.info).toHaveBeenCalledWith( + `Retrying resource initialization for context "test"` + ); + expect(logger.warn).toHaveBeenCalledWith( + expect.stringMatching( + /There was an error in the framework installing namespace-level resources and creating concrete indices for context "test" - Original error: Failure during installation\. fail \d+; Error after retry: Failure during installation\. fail \d+/ + ) + ); + }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(4); - }); + test('should return null if retrying common resources initialization fails again with same error', async () => { + clusterClient.cluster.putComponentTemplate.mockRejectedValue(new Error('fail')); + + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + alertsService.register(TestRegistrationContext); + + await retryUntil('error log called', async () => logger.error.mock.calls.length > 0); + + expect(alertsService.isInitialized()).toEqual(false); + + // Installing component template failed so no calls to install context-specific resources + // should be made + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 1 + ); + expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + + const result = await alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 0 : 2 + ); + expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); + expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); + expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); + expect(clusterClient.indices.create).not.toHaveBeenCalled(); + + expect(result).toBe(null); + expect(AlertsClient).not.toHaveBeenCalled(); + expect(logger.info).toHaveBeenCalledWith(`Retrying common resource initialization`); + expect(logger.info).toHaveBeenCalledWith( + `Retrying resource initialization for context "test"` + ); + expect(logger.warn).toHaveBeenCalledWith( + `There was an error in the framework installing namespace-level resources and creating concrete indices for context "test" - Retry failed with error: Failure during installation. fail` + ); + }); - test('should retry updating index mappings for existing indices for transient ES errors', async () => { - clusterClient.indices.putMapping - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockResolvedValue({ acknowledged: true }); - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', + test('should return null if retrying context specific initialization fails again', async () => { + clusterClient.indices.simulateTemplate.mockImplementationOnce(async () => ({ + ...SimulateTemplateResponse, + template: { + ...SimulateTemplateResponse.template, + mappings: {}, + }, + })); + clusterClient.indices.putIndexTemplate.mockRejectedValueOnce( + new Error('fail index template') + ); + + alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + alertsService.register(TestRegistrationContext); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + + const result = await alertsService.createAlertsClient({ + logger, + ruleType: ruleTypeWithAlertDefinition, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); + + expect(AlertsClient).not.toHaveBeenCalled(); + expect(result).toBe(null); + expect(logger.info).not.toHaveBeenCalledWith(`Retrying common resource initialization`); + expect(logger.info).toHaveBeenCalledWith( + `Retrying resource initialization for context "test"` + ); + expect(logger.warn).toHaveBeenCalledWith( + `There was an error in the framework installing namespace-level resources and creating concrete indices for context "test" - Original error: Failure during installation. No mappings would be generated for .alerts-test.alerts-default-index-template, possibly due to failed/misconfigured bootstrapping; Error after retry: Failure during installation. fail index template` + ); + }); }); - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); - - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); - - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(4); - }); + describe('retries', () => { + test('should retry adding ILM policy for transient ES errors', async () => { + if (useDataStreamForAlerts) return; + + clusterClient.ilm.putLifecycle + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ acknowledged: true }); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(3); + }); - test('should retry creating concrete index for transient ES errors', async () => { - clusterClient.indices.create - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockResolvedValue({ index: 'index', shards_acknowledged: true, acknowledged: true }); - const alertsService = new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - }); + test('should retry adding component template for transient ES errors', async () => { + clusterClient.cluster.putComponentTemplate + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ acknowledged: true }); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(5); + }); - await retryUntil( - 'alert service initialized', - async () => alertsService.isInitialized() === true - ); + test('should retry updating index template for transient ES errors', async () => { + clusterClient.indices.putIndexTemplate + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ acknowledged: true }); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + expect(alertsService.isInitialized()).toEqual(true); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(3); + }); - alertsService.register(TestRegistrationContext); - await retryUntil( - 'context initialized', - async () => (await getContextInitialized(alertsService)) === true - ); + test('should retry updating index settings for existing indices for transient ES errors', async () => { + clusterClient.indices.putSettings + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ acknowledged: true }); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(3); + } else { + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(4); + } + }); - expect(clusterClient.indices.create).toHaveBeenCalledTimes(3); - }); - }); + test('should retry updating index mappings for existing indices for transient ES errors', async () => { + clusterClient.indices.putMapping + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ acknowledged: true }); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes( + useDataStreamForAlerts ? 3 : 4 + ); + }); - describe('timeout', () => { - test('should short circuit initialization if timeout exceeded', async () => { - clusterClient.ilm.putLifecycle.mockImplementationOnce(async () => { - await new Promise((resolve) => setTimeout(resolve, 20)); - return { acknowledged: true }; - }); - new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - timeoutMs: 10, + test('should retry creating concrete index for transient ES errors', async () => { + clusterClient.indices.getDataStream.mockImplementationOnce(async () => ({ + data_streams: [], + })); + clusterClient.indices.createDataStream + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ acknowledged: true }); + clusterClient.indices.create + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ index: 'index', shards_acknowledged: true, acknowledged: true }); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + dataStreamAdapter, + }); + + await retryUntil( + 'alert service initialized', + async () => alertsService.isInitialized() === true + ); + + alertsService.register(TestRegistrationContext); + await retryUntil( + 'context initialized', + async () => (await getContextInitialized(alertsService)) === true + ); + + if (useDataStreamForAlerts) { + expect(clusterClient.indices.createDataStream).toHaveBeenCalledTimes(3); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledTimes(3); + } + }); }); - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - - expect(logger.error).toHaveBeenCalledWith(new Error(`Timeout: it took more than 10ms`)); - }); + describe('timeout', () => { + test('should short circuit initialization if timeout exceeded', async () => { + clusterClient.cluster.putComponentTemplate.mockImplementationOnce(async () => { + await new Promise((resolve) => setTimeout(resolve, 20)); + return { acknowledged: true }; + }); + new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + timeoutMs: 10, + dataStreamAdapter, + }); + + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + + expect(logger.error).toHaveBeenCalledWith(new Error(`Timeout: it took more than 10ms`)); + }); - test('should short circuit initialization if pluginStop$ signal received but not throw error', async () => { - pluginStop$.next(); - new AlertsService({ - logger, - elasticsearchClientPromise: Promise.resolve(clusterClient), - pluginStop$, - kibanaVersion: '8.8.0', - timeoutMs: 10, + test('should short circuit initialization if pluginStop$ signal received but not throw error', async () => { + pluginStop$.next(); + new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + kibanaVersion: '8.8.0', + timeoutMs: 10, + dataStreamAdapter, + }); + + await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); + + expect(logger.error).toHaveBeenCalledWith( + new Error(`Server is stopping; must stop all async operations`) + ); + }); }); - - await retryUntil('error logger called', async () => logger.error.mock.calls.length > 0); - - expect(logger.error).toHaveBeenCalledWith( - new Error(`Server is stopping; must stop all async operations`) - ); }); - }); + } }); diff --git a/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts b/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts index e8ecab61e76d9..d0c9474389ef0 100644 --- a/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts +++ b/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts @@ -19,7 +19,13 @@ import { getComponentTemplateName, getIndexTemplateAndPattern, } from './resource_installer_utils'; -import { AlertInstanceContext, AlertInstanceState, IRuleTypeAlerts, RuleAlertData } from '../types'; +import { + AlertInstanceContext, + AlertInstanceState, + IRuleTypeAlerts, + RuleAlertData, + DataStreamAdapter, +} from '../types'; import { createResourceInstallationHelper, errorResult, @@ -49,6 +55,7 @@ interface AlertsServiceParams { kibanaVersion: string; elasticsearchClientPromise: Promise; timeoutMs?: number; + dataStreamAdapter: DataStreamAdapter; } export interface CreateAlertsClientParams extends LegacyAlertsClientParams { @@ -114,10 +121,13 @@ export class AlertsService implements IAlertsService { private resourceInitializationHelper: ResourceInstallationHelper; private registeredContexts: Map = new Map(); private commonInitPromise: Promise; + private dataStreamAdapter: DataStreamAdapter; constructor(private readonly options: AlertsServiceParams) { this.initialized = false; + this.dataStreamAdapter = options.dataStreamAdapter; + // Kick off initialization of common assets and save the promise this.commonInitPromise = this.initializeCommon(this.options.timeoutMs); @@ -221,6 +231,7 @@ export class AlertsService implements IAlertsService { namespace: opts.namespace, rule: opts.rule, kibanaVersion: this.options.kibanaVersion, + dataStreamAdapter: this.dataStreamAdapter, }); } @@ -296,6 +307,7 @@ export class AlertsService implements IAlertsService { esClient, name: DEFAULT_ALERTS_ILM_POLICY_NAME, policy: DEFAULT_ALERTS_ILM_POLICY, + dataStreamAdapter: this.dataStreamAdapter, }), () => createOrUpdateComponentTemplate({ @@ -421,6 +433,7 @@ export class AlertsService implements IAlertsService { kibanaVersion: this.options.kibanaVersion, namespace, totalFieldsLimit: TOTAL_FIELDS_LIMIT, + dataStreamAdapter: this.dataStreamAdapter, }), }), async () => @@ -429,6 +442,7 @@ export class AlertsService implements IAlertsService { esClient, totalFieldsLimit: TOTAL_FIELDS_LIMIT, indexPatterns: indexTemplateAndPattern, + dataStreamAdapter: this.dataStreamAdapter, }), ]); diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.test.ts b/x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.test.ts index a4cb6a26d3767..e2ee309b123f5 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.test.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.test.ts @@ -6,7 +6,9 @@ */ import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { errors as EsErrors } from '@elastic/elasticsearch'; +import { IndicesGetDataStreamResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { createConcreteWriteIndex } from './create_concrete_write_index'; +import { getDataStreamAdapter } from './data_stream_adapter'; const randomDelayMultiplier = 0.01; const logger = loggingSystemMock.createLogger(); @@ -36,6 +38,10 @@ const GetAliasResponse = { }, }; +const GetDataStreamResponse = { + data_streams: ['any-content-here-means-already-exists'], +} as unknown as IndicesGetDataStreamResponse; + const SimulateTemplateResponse = { template: { aliases: { @@ -60,483 +66,609 @@ const IndexPatterns = { }; describe('createConcreteWriteIndex', () => { - beforeEach(() => { - jest.resetAllMocks(); - jest.spyOn(global.Math, 'random').mockReturnValue(randomDelayMultiplier); - }); - - it(`should call esClient to put index template`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => ({})); - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + for (const useDataStream of [false, true]) { + const label = useDataStream ? 'data streams' : 'aliases'; + const dataStreamAdapter = getDataStreamAdapter({ useDataStreamForAlerts: useDataStream }); - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, - }, - }, + beforeEach(() => { + jest.resetAllMocks(); + jest.spyOn(global.Math, 'random').mockReturnValue(randomDelayMultiplier); }); - }); - - it(`should retry on transient ES errors`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => ({})); - clusterClient.indices.create - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockResolvedValue({ - index: '.internal.alerts-test.alerts-default-000001', - shards_acknowledged: true, - acknowledged: true, + + describe(`using ${label} for alert indices`, () => { + it(`should call esClient to put index template`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => ({})); + clusterClient.indices.getDataStream.mockImplementation(async () => ({ data_streams: [] })); + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + if (useDataStream) { + expect(clusterClient.indices.createDataStream).toHaveBeenCalledWith({ + name: '.alerts-test.alerts-default', + }); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + } }); - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); - expect(clusterClient.indices.create).toHaveBeenCalledTimes(3); - }); - - it(`should log and throw error if max retries exceeded`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => ({})); - clusterClient.indices.create.mockRejectedValue(new EsErrors.ConnectionError('foo')); - await expect(() => - createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"foo"`); - - expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - foo`); - expect(clusterClient.indices.create).toHaveBeenCalledTimes(4); - }); - - it(`should log and throw error if ES throws error`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => ({})); - clusterClient.indices.create.mockRejectedValueOnce(new Error('generic error')); - - await expect(() => - createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"generic error"`); - - expect(logger.error).toHaveBeenCalledWith( - `Error creating concrete write index - generic error` - ); - }); - - it(`should log and return if ES throws resource_already_exists_exception error and existing index is already write index`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => ({})); - const error = new Error(`fail`) as EsError; - error.meta = { - body: { - error: { - type: 'resource_already_exists_exception', - }, - }, - }; - clusterClient.indices.create.mockRejectedValueOnce(error); - clusterClient.indices.get.mockImplementationOnce(async () => ({ - '.internal.alerts-test.alerts-default-000001': { - aliases: { '.alerts-test.alerts-default': { is_write_index: true } }, - }, - })); + it(`should retry on transient ES errors`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => ({})); + clusterClient.indices.getDataStream.mockImplementation(async () => ({ data_streams: [] })); + clusterClient.indices.create + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ + index: '.internal.alerts-test.alerts-default-000001', + shards_acknowledged: true, + acknowledged: true, + }); + clusterClient.indices.createDataStream + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ + acknowledged: true, + }); + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + if (useDataStream) { + expect(clusterClient.indices.createDataStream).toHaveBeenCalledTimes(3); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledTimes(3); + } + }); - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + it(`should log and throw error if max retries exceeded`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => ({})); + clusterClient.indices.getDataStream.mockImplementation(async () => ({ data_streams: [] })); + clusterClient.indices.create.mockRejectedValue(new EsErrors.ConnectionError('foo')); + clusterClient.indices.createDataStream.mockRejectedValue( + new EsErrors.ConnectionError('foo') + ); + await expect(() => + createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"foo"`); + + expect(logger.error).toHaveBeenCalledWith( + useDataStream + ? `Error creating data stream .alerts-test.alerts-default - foo` + : `Error creating concrete write index - foo` + ); + + if (useDataStream) { + expect(clusterClient.indices.createDataStream).toHaveBeenCalledTimes(4); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledTimes(4); + } + }); - expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); - }); - - it(`should retry getting index on transient ES error`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => ({})); - const error = new Error(`fail`) as EsError; - error.meta = { - body: { - error: { - type: 'resource_already_exists_exception', - }, - }, - }; - clusterClient.indices.create.mockRejectedValueOnce(error); - clusterClient.indices.get - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockImplementationOnce(async () => ({ - '.internal.alerts-test.alerts-default-000001': { - aliases: { '.alerts-test.alerts-default': { is_write_index: true } }, - }, - })); - - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + it(`should log and throw error if ES throws error`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => ({})); + clusterClient.indices.getDataStream.mockImplementation(async () => ({ data_streams: [] })); + clusterClient.indices.create.mockRejectedValueOnce(new Error('generic error')); + clusterClient.indices.createDataStream.mockRejectedValueOnce(new Error('generic error')); + + await expect(() => + createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"generic error"`); + + expect(logger.error).toHaveBeenCalledWith( + useDataStream + ? `Error creating data stream .alerts-test.alerts-default - generic error` + : `Error creating concrete write index - generic error` + ); + }); - expect(clusterClient.indices.get).toHaveBeenCalledTimes(3); - expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); - }); - - it(`should log and throw error if ES throws resource_already_exists_exception error and existing index is not the write index`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => ({})); - const error = new Error(`fail`) as EsError; - error.meta = { - body: { - error: { - type: 'resource_already_exists_exception', - }, - }, - }; - clusterClient.indices.create.mockRejectedValueOnce(error); - clusterClient.indices.get.mockImplementationOnce(async () => ({ - '.internal.alerts-test.alerts-default-000001': { - aliases: { '.alerts-test.alerts-default': { is_write_index: false } }, - }, - })); - - await expect(() => - createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Attempted to create index: .internal.alerts-test.alerts-default-000001 as the write index for alias: .alerts-test.alerts-default, but the index already exists and is not the write index for the alias"` - ); - expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); - }); - - it(`should call esClient to put index template if get alias throws 404`, async () => { - const error = new Error(`not found`) as EsError; - error.statusCode = 404; - clusterClient.indices.getAlias.mockRejectedValueOnce(error); - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + it(`should log and return if ES throws resource_already_exists_exception error and existing index is already write index`, async () => { + if (useDataStream) return; - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, + clusterClient.indices.getAlias.mockImplementation(async () => ({})); + const error = new Error(`fail`) as EsError; + error.meta = { + body: { + error: { + type: 'resource_already_exists_exception', + }, }, - }, - }, - }); - }); - - it(`should log and throw error if get alias throws non-404 error`, async () => { - const error = new Error(`fatal error`) as EsError; - error.statusCode = 500; - clusterClient.indices.getAlias.mockRejectedValueOnce(error); - - await expect(() => - createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"fatal error"`); - expect(logger.error).toHaveBeenCalledWith( - `Error fetching concrete indices for .internal.alerts-test.alerts-default-* pattern - fatal error` - ); - }); - - it(`should update underlying settings and mappings of existing concrete indices if they exist`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockImplementation( - async () => SimulateTemplateResponse - ); - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + }; + clusterClient.indices.create.mockRejectedValueOnce(error); + clusterClient.indices.get.mockImplementationOnce(async () => ({ + '.internal.alerts-test.alerts-default-000001': { + aliases: { '.alerts-test.alerts-default': { is_write_index: true } }, + }, + })); + + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); + }); - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, + it(`should retry getting index on transient ES error`, async () => { + if (useDataStream) return; + clusterClient.indices.getAlias.mockImplementation(async () => ({})); + const error = new Error(`fail`) as EsError; + error.statusCode = 404; + error.meta = { + body: { + error: { + type: 'resource_already_exists_exception', + }, }, - }, - }, - }); + }; + clusterClient.indices.create.mockRejectedValueOnce(error); + clusterClient.indices.get + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockImplementationOnce(async () => ({ + '.internal.alerts-test.alerts-default-000001': { + aliases: { '.alerts-test.alerts-default': { is_write_index: true } }, + }, + })); + + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + expect(clusterClient.indices.get).toHaveBeenCalledTimes(3); + expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); + }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); - }); - - it(`should retry simulateIndexTemplate on transient ES errors`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockImplementation(async () => SimulateTemplateResponse); - - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + it(`should log and throw error if ES throws resource_already_exists_exception error and existing index is not the write index`, async () => { + if (useDataStream) return; - expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(4); - }); - - it(`should retry getting alias on transient ES errors`, async () => { - clusterClient.indices.getAlias - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockImplementation( - async () => SimulateTemplateResponse - ); - - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + clusterClient.indices.getAlias.mockImplementation(async () => ({})); + const error = new Error(`fail`) as EsError; + error.meta = { + body: { + error: { + type: 'resource_already_exists_exception', + }, + }, + }; + clusterClient.indices.create.mockRejectedValueOnce(error); + clusterClient.indices.get.mockImplementationOnce(async () => ({ + '.internal.alerts-test.alerts-default-000001': { + aliases: { '.alerts-test.alerts-default': { is_write_index: false } }, + }, + })); - expect(clusterClient.indices.getAlias).toHaveBeenCalledTimes(3); - }); - - it(`should retry settings update on transient ES errors`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockImplementation( - async () => SimulateTemplateResponse - ); - clusterClient.indices.putSettings - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockResolvedValue({ acknowledged: true }); - - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + const ccwiPromise = createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(4); - }); - - it(`should log and throw error on settings update if max retries exceeded`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockImplementation( - async () => SimulateTemplateResponse - ); - clusterClient.indices.putSettings.mockRejectedValue(new EsErrors.ConnectionError('foo')); - await expect(() => - createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"foo"`); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(7); - expect(logger.error).toHaveBeenCalledWith( - `Failed to PUT index.mapping.total_fields.limit settings for alias alias_1: foo` - ); - }); - - it(`should log and throw error on settings update if ES throws error`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockImplementation( - async () => SimulateTemplateResponse - ); - clusterClient.indices.putSettings.mockRejectedValue(new Error('generic error')); - - await expect(() => - createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"generic error"`); - - expect(logger.error).toHaveBeenCalledWith( - `Failed to PUT index.mapping.total_fields.limit settings for alias alias_1: generic error` - ); - }); - - it(`should retry mappings update on transient ES errors`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockImplementation( - async () => SimulateTemplateResponse - ); - clusterClient.indices.putMapping - .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) - .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) - .mockResolvedValue({ acknowledged: true }); - - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + await expect(() => ccwiPromise).rejects.toThrowErrorMatchingInlineSnapshot( + `"Attempted to create index: .internal.alerts-test.alerts-default-000001 as the write index for alias: .alerts-test.alerts-default, but the index already exists and is not the write index for the alias"` + ); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(4); - }); - - it(`should log and throw error on mappings update if max retries exceeded`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockImplementation( - async () => SimulateTemplateResponse - ); - clusterClient.indices.putMapping.mockRejectedValue(new EsErrors.ConnectionError('foo')); - await expect(() => - createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"foo"`); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(7); - expect(logger.error).toHaveBeenCalledWith(`Failed to PUT mapping for alias alias_1: foo`); - }); - - it(`should log and throw error on mappings update if ES throws error`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockImplementation( - async () => SimulateTemplateResponse - ); - clusterClient.indices.putMapping.mockRejectedValue(new Error('generic error')); - - await expect(() => - createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"generic error"`); - - expect(logger.error).toHaveBeenCalledWith( - `Failed to PUT mapping for alias alias_1: generic error` - ); - }); - - it(`should log and return when simulating updated mappings throws error`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockRejectedValueOnce(new Error('fail')); - - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); + }); - expect(logger.error).toHaveBeenCalledWith( - `Ignored PUT mappings for alias alias_1; error generating simulated mappings: fail` - ); + it(`should call esClient to put index template if get alias throws 404`, async () => { + const error = new Error(`not found`) as EsError; + error.statusCode = 404; + clusterClient.indices.getAlias.mockRejectedValueOnce(error); + clusterClient.indices.getDataStream.mockRejectedValueOnce(error); + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + if (useDataStream) { + expect(clusterClient.indices.createDataStream).toHaveBeenCalledWith({ + name: '.alerts-test.alerts-default', + }); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + } + }); - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, - }, - }, - }, - }); - }); - - it(`should log and return when simulating updated mappings returns null`, async () => { - clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); - clusterClient.indices.simulateIndexTemplate.mockImplementationOnce(async () => ({ - ...SimulateTemplateResponse, - template: { ...SimulateTemplateResponse.template, mappings: null }, - })); - - await createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }); + it(`should log and throw error if get alias throws non-404 error`, async () => { + const error = new Error(`fatal error`) as EsError; + error.statusCode = 500; + clusterClient.indices.getAlias.mockRejectedValueOnce(error); + clusterClient.indices.getDataStream.mockRejectedValueOnce(error); + + await expect(() => + createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"fatal error"`); + expect(logger.error).toHaveBeenCalledWith( + useDataStream + ? `Error fetching data stream for .alerts-test.alerts-default - fatal error` + : `Error fetching concrete indices for .internal.alerts-test.alerts-default-* pattern - fatal error` + ); + }); - expect(logger.error).toHaveBeenCalledWith( - `Ignored PUT mappings for alias alias_1; simulated mappings were empty` - ); + it(`should update underlying settings and mappings of existing concrete indices if they exist`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockImplementation( + async () => SimulateTemplateResponse + ); + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + if (!useDataStream) { + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + } + + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(useDataStream ? 1 : 2); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(useDataStream ? 1 : 2); + }); + + it(`should retry simulateIndexTemplate on transient ES errors`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockImplementation(async () => SimulateTemplateResponse); + + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes( + useDataStream ? 3 : 4 + ); + }); + + it(`should retry getting alias on transient ES errors`, async () => { + clusterClient.indices.getAlias + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockImplementation( + async () => SimulateTemplateResponse + ); + + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + if (useDataStream) { + expect(clusterClient.indices.getDataStream).toHaveBeenCalledTimes(3); + } else { + expect(clusterClient.indices.getAlias).toHaveBeenCalledTimes(3); + } + }); + + it(`should retry settings update on transient ES errors`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockImplementation( + async () => SimulateTemplateResponse + ); + clusterClient.indices.putSettings + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ acknowledged: true }); + + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(useDataStream ? 3 : 4); + }); + + it(`should log and throw error on settings update if max retries exceeded`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockImplementation( + async () => SimulateTemplateResponse + ); + clusterClient.indices.putSettings.mockRejectedValue(new EsErrors.ConnectionError('foo')); + await expect(() => + createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"foo"`); + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(useDataStream ? 4 : 7); + expect(logger.error).toHaveBeenCalledWith( + useDataStream + ? `Failed to PUT index.mapping.total_fields.limit settings for .alerts-test.alerts-default: foo` + : `Failed to PUT index.mapping.total_fields.limit settings for alias_1: foo` + ); + }); - expect(clusterClient.indices.create).toHaveBeenCalledWith({ - index: '.internal.alerts-test.alerts-default-000001', - body: { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: true, + it(`should log and throw error on settings update if ES throws error`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockImplementation( + async () => SimulateTemplateResponse + ); + clusterClient.indices.putSettings.mockRejectedValue(new Error('generic error')); + + await expect(() => + createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"generic error"`); + + expect(logger.error).toHaveBeenCalledWith( + useDataStream + ? `Failed to PUT index.mapping.total_fields.limit settings for .alerts-test.alerts-default: generic error` + : `Failed to PUT index.mapping.total_fields.limit settings for alias_1: generic error` + ); + }); + + it(`should retry mappings update on transient ES errors`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockImplementation( + async () => SimulateTemplateResponse + ); + clusterClient.indices.putMapping + .mockRejectedValueOnce(new EsErrors.ConnectionError('foo')) + .mockRejectedValueOnce(new EsErrors.TimeoutError('timeout')) + .mockResolvedValue({ acknowledged: true }); + + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(useDataStream ? 3 : 4); + }); + + it(`should log and throw error on mappings update if max retries exceeded`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockImplementation( + async () => SimulateTemplateResponse + ); + clusterClient.indices.putMapping.mockRejectedValue(new EsErrors.ConnectionError('foo')); + await expect(() => + createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"foo"`); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(useDataStream ? 4 : 7); + expect(logger.error).toHaveBeenCalledWith( + useDataStream + ? `Failed to PUT mapping for .alerts-test.alerts-default: foo` + : `Failed to PUT mapping for alias_1: foo` + ); + }); + + it(`should log and throw error on mappings update if ES throws error`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockImplementation( + async () => SimulateTemplateResponse + ); + clusterClient.indices.putMapping.mockRejectedValue(new Error('generic error')); + + await expect(() => + createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"generic error"`); + + expect(logger.error).toHaveBeenCalledWith( + useDataStream + ? `Failed to PUT mapping for .alerts-test.alerts-default: generic error` + : `Failed to PUT mapping for alias_1: generic error` + ); + }); + + it(`should log and return when simulating updated mappings throws error`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockRejectedValueOnce(new Error('fail')); + + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + expect(logger.error).toHaveBeenCalledWith( + useDataStream + ? `Ignored PUT mappings for .alerts-test.alerts-default; error generating simulated mappings: fail` + : `Ignored PUT mappings for alias_1; error generating simulated mappings: fail` + ); + + if (useDataStream) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + } + }); + + it(`should log and return when simulating updated mappings returns null`, async () => { + clusterClient.indices.getAlias.mockImplementation(async () => GetAliasResponse); + clusterClient.indices.getDataStream.mockImplementation(async () => GetDataStreamResponse); + clusterClient.indices.simulateIndexTemplate.mockImplementationOnce(async () => ({ + ...SimulateTemplateResponse, + template: { ...SimulateTemplateResponse.template, mappings: null }, + })); + + await createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }); + + expect(logger.error).toHaveBeenCalledWith( + useDataStream + ? `Ignored PUT mappings for .alerts-test.alerts-default; simulated mappings were empty` + : `Ignored PUT mappings for alias_1; simulated mappings were empty` + ); + + if (useDataStream) { + expect(clusterClient.indices.createDataStream).not.toHaveBeenCalled(); + } else { + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.internal.alerts-test.alerts-default-000001', + body: { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: true, + }, + }, + }, + }); + } + }); + + it(`should throw error when there are concrete indices but none of them are the write index`, async () => { + if (useDataStream) return; + + clusterClient.indices.getAlias.mockImplementationOnce(async () => ({ + '.internal.alerts-test.alerts-default-0001': { + aliases: { + '.alerts-test.alerts-default': { + is_write_index: false, + is_hidden: true, + }, + alias_2: { + is_write_index: false, + is_hidden: true, + }, + }, }, - }, - }, + })); + clusterClient.indices.simulateIndexTemplate.mockImplementation( + async () => SimulateTemplateResponse + ); + + await expect(() => + createConcreteWriteIndex({ + logger, + esClient: clusterClient, + indexPatterns: IndexPatterns, + totalFieldsLimit: 2500, + dataStreamAdapter, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default"` + ); + }); }); - }); - - it(`should throw error when there are concrete indices but none of them are the write index`, async () => { - clusterClient.indices.getAlias.mockImplementationOnce(async () => ({ - '.internal.alerts-test.alerts-default-0001': { - aliases: { - '.alerts-test.alerts-default': { - is_write_index: false, - is_hidden: true, - }, - alias_2: { - is_write_index: false, - is_hidden: true, - }, - }, - }, - })); - clusterClient.indices.simulateIndexTemplate.mockImplementation( - async () => SimulateTemplateResponse - ); - - await expect(() => - createConcreteWriteIndex({ - logger, - esClient: clusterClient, - indexPatterns: IndexPatterns, - totalFieldsLimit: 2500, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Indices matching pattern .internal.alerts-test.alerts-default-* exist but none are set as the write index for alias .alerts-test.alerts-default"` - ); - }); + } }); diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.ts b/x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.ts index 31aface312913..8ad628e1b2905 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.ts @@ -10,8 +10,9 @@ import { Logger, ElasticsearchClient } from '@kbn/core/server'; import { get } from 'lodash'; import { IIndexPatternString } from '../resource_installer_utils'; import { retryTransientEsErrors } from './retry_transient_es_errors'; +import { DataStreamAdapter } from './data_stream_adapter'; -interface ConcreteIndexInfo { +export interface ConcreteIndexInfo { index: string; alias: string; isWriteIndex: boolean; @@ -50,7 +51,7 @@ const updateTotalFieldLimitSetting = async ({ return; } catch (err) { logger.error( - `Failed to PUT index.mapping.total_fields.limit settings for alias ${alias}: ${err.message}` + `Failed to PUT index.mapping.total_fields.limit settings for ${alias}: ${err.message}` ); throw err; } @@ -74,7 +75,7 @@ const updateUnderlyingMapping = async ({ ); } catch (err) { logger.error( - `Ignored PUT mappings for alias ${alias}; error generating simulated mappings: ${err.message}` + `Ignored PUT mappings for ${alias}; error generating simulated mappings: ${err.message}` ); return; } @@ -82,7 +83,7 @@ const updateUnderlyingMapping = async ({ const simulatedMapping = get(simulatedIndexMapping, ['template', 'mappings']); if (simulatedMapping == null) { - logger.error(`Ignored PUT mappings for alias ${alias}; simulated mappings were empty`); + logger.error(`Ignored PUT mappings for ${alias}; simulated mappings were empty`); return; } @@ -94,20 +95,22 @@ const updateUnderlyingMapping = async ({ return; } catch (err) { - logger.error(`Failed to PUT mapping for alias ${alias}: ${err.message}`); + logger.error(`Failed to PUT mapping for ${alias}: ${err.message}`); throw err; } }; /** * Updates the underlying mapping for any existing concrete indices */ -const updateIndexMappings = async ({ +export const updateIndexMappings = async ({ logger, esClient, totalFieldsLimit, concreteIndices, }: UpdateIndexMappingsOpts) => { - logger.debug(`Updating underlying mappings for ${concreteIndices.length} indices.`); + logger.debug( + `Updating underlying mappings for ${concreteIndices.length} indices / data streams.` + ); // Update total field limit setting of found indices // Other index setting changes are not updated at this time @@ -125,11 +128,12 @@ const updateIndexMappings = async ({ ); }; -interface CreateConcreteWriteIndexOpts { +export interface CreateConcreteWriteIndexOpts { logger: Logger; esClient: ElasticsearchClient; totalFieldsLimit: number; indexPatterns: IIndexPatternString; + dataStreamAdapter: DataStreamAdapter; } /** * Installs index template that uses installed component template @@ -137,107 +141,6 @@ interface CreateConcreteWriteIndexOpts { * conflicts. Simulate should return an empty mapping if a template * conflicts with an already installed template. */ -export const createConcreteWriteIndex = async ({ - logger, - esClient, - indexPatterns, - totalFieldsLimit, -}: CreateConcreteWriteIndexOpts) => { - logger.info(`Creating concrete write index - ${indexPatterns.name}`); - - // check if a concrete write index already exists - let concreteIndices: ConcreteIndexInfo[] = []; - try { - // Specify both the index pattern for the backing indices and their aliases - // The alias prevents the request from finding other namespaces that could match the -* pattern - const response = await retryTransientEsErrors( - () => - esClient.indices.getAlias({ - index: indexPatterns.pattern, - name: indexPatterns.basePattern, - }), - { logger } - ); - - concreteIndices = Object.entries(response).flatMap(([index, { aliases }]) => - Object.entries(aliases).map(([aliasName, aliasProperties]) => ({ - index, - alias: aliasName, - isWriteIndex: aliasProperties.is_write_index ?? false, - })) - ); - - logger.debug( - `Found ${concreteIndices.length} concrete indices for ${ - indexPatterns.name - } - ${JSON.stringify(concreteIndices)}` - ); - } catch (error) { - // 404 is expected if no concrete write indices have been created - if (error.statusCode !== 404) { - logger.error( - `Error fetching concrete indices for ${indexPatterns.pattern} pattern - ${error.message}` - ); - throw error; - } - } - - let concreteWriteIndicesExist = false; - // if a concrete write index already exists, update the underlying mapping - if (concreteIndices.length > 0) { - await updateIndexMappings({ logger, esClient, totalFieldsLimit, concreteIndices }); - - const concreteIndicesExist = concreteIndices.some( - (index) => index.alias === indexPatterns.alias - ); - concreteWriteIndicesExist = concreteIndices.some( - (index) => index.alias === indexPatterns.alias && index.isWriteIndex - ); - - // If there are some concrete indices but none of them are the write index, we'll throw an error - // because one of the existing indices should have been the write target. - if (concreteIndicesExist && !concreteWriteIndicesExist) { - throw new Error( - `Indices matching pattern ${indexPatterns.pattern} exist but none are set as the write index for alias ${indexPatterns.alias}` - ); - } - } - - // check if a concrete write index already exists - if (!concreteWriteIndicesExist) { - try { - await retryTransientEsErrors( - () => - esClient.indices.create({ - index: indexPatterns.name, - body: { - aliases: { - [indexPatterns.alias]: { - is_write_index: true, - }, - }, - }, - }), - { logger } - ); - } catch (error) { - logger.error(`Error creating concrete write index - ${error.message}`); - // If the index already exists and it's the write index for the alias, - // something else created it so suppress the error. If it's not the write - // index, that's bad, throw an error. - if (error?.meta?.body?.error?.type === 'resource_already_exists_exception') { - const existingIndices = await retryTransientEsErrors( - () => esClient.indices.get({ index: indexPatterns.name }), - { logger } - ); - if (!existingIndices[indexPatterns.name]?.aliases?.[indexPatterns.alias]?.is_write_index) { - throw Error( - `Attempted to create index: ${indexPatterns.name} as the write index for alias: ${indexPatterns.alias}, but the index already exists and is not the write index for the alias` - ); - } - } else { - throw error; - } - } - } +export const createConcreteWriteIndex = async (opts: CreateConcreteWriteIndexOpts) => { + await opts.dataStreamAdapter.createStream(opts); }; diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_ilm_policy.test.ts b/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_ilm_policy.test.ts index e47bc92eb5ae0..8cacdb1e97563 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_ilm_policy.test.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_ilm_policy.test.ts @@ -7,10 +7,12 @@ import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { errors as EsErrors } from '@elastic/elasticsearch'; import { createOrUpdateIlmPolicy } from './create_or_update_ilm_policy'; +import { getDataStreamAdapter } from './data_stream_adapter'; const randomDelayMultiplier = 0.01; const logger = loggingSystemMock.createLogger(); const clusterClient = elasticsearchServiceMock.createClusterClient().asInternalUser; +const dataStreamAdapter = getDataStreamAdapter({ useDataStreamForAlerts: false }); const IlmPolicy = { _meta: { @@ -40,6 +42,7 @@ describe('createOrUpdateIlmPolicy', () => { esClient: clusterClient, name: 'test-policy', policy: IlmPolicy, + dataStreamAdapter, }); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith({ @@ -58,6 +61,7 @@ describe('createOrUpdateIlmPolicy', () => { esClient: clusterClient, name: 'test-policy', policy: IlmPolicy, + dataStreamAdapter, }); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledTimes(3); @@ -71,6 +75,7 @@ describe('createOrUpdateIlmPolicy', () => { esClient: clusterClient, name: 'test-policy', policy: IlmPolicy, + dataStreamAdapter, }) ).rejects.toThrowErrorMatchingInlineSnapshot(`"foo"`); @@ -87,6 +92,7 @@ describe('createOrUpdateIlmPolicy', () => { esClient: clusterClient, name: 'test-policy', policy: IlmPolicy, + dataStreamAdapter, }) ).rejects.toThrowErrorMatchingInlineSnapshot(`"generic error"`); diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_ilm_policy.ts b/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_ilm_policy.ts index d1c50b7474436..dfc967aa974d6 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_ilm_policy.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_ilm_policy.ts @@ -8,12 +8,14 @@ import { IlmPolicy } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger, ElasticsearchClient } from '@kbn/core/server'; import { retryTransientEsErrors } from './retry_transient_es_errors'; +import { DataStreamAdapter } from './data_stream_adapter'; interface CreateOrUpdateIlmPolicyOpts { logger: Logger; esClient: ElasticsearchClient; name: string; policy: IlmPolicy; + dataStreamAdapter: DataStreamAdapter; } /** * Creates ILM policy if it doesn't already exist, updates it if it does @@ -23,7 +25,10 @@ export const createOrUpdateIlmPolicy = async ({ esClient, name, policy, + dataStreamAdapter, }: CreateOrUpdateIlmPolicyOpts) => { + if (dataStreamAdapter.isUsingDataStreams()) return; + logger.info(`Installing ILM policy ${name}`); try { diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_index_template.test.ts b/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_index_template.test.ts index d4ce203a0d0e3..bf0ae8797eca5 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_index_template.test.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_index_template.test.ts @@ -7,12 +7,14 @@ import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { errors as EsErrors } from '@elastic/elasticsearch'; import { getIndexTemplate, createOrUpdateIndexTemplate } from './create_or_update_index_template'; +import { createDataStreamAdapterMock } from './data_stream_adapter.mock'; +import { DataStreamAdapter } from './data_stream_adapter'; const randomDelayMultiplier = 0.01; const logger = loggingSystemMock.createLogger(); const clusterClient = elasticsearchServiceMock.createClusterClient().asInternalUser; -const IndexTemplate = (namespace: string = 'default') => ({ +const IndexTemplate = (namespace: string = 'default', useDataStream: boolean = false) => ({ name: `.alerts-test.alerts-${namespace}-index-template`, body: { _meta: { @@ -38,10 +40,14 @@ const IndexTemplate = (namespace: string = 'default') => ({ settings: { auto_expand_replicas: '0-1', hidden: true, - 'index.lifecycle': { - name: 'test-ilm-policy', - rollover_alias: `.alerts-test.alerts-${namespace}`, - }, + ...(useDataStream + ? {} + : { + 'index.lifecycle': { + name: 'test-ilm-policy', + rollover_alias: `.alerts-test.alerts-${namespace}`, + }, + }), 'index.mapping.total_fields.limit': 2500, }, }, @@ -65,7 +71,20 @@ const SimulateTemplateResponse = { }; describe('getIndexTemplate', () => { + let dataStreamAdapter: DataStreamAdapter; + let useDataStream: boolean; + + beforeEach(() => { + dataStreamAdapter = createDataStreamAdapterMock(); + useDataStream = dataStreamAdapter.isUsingDataStreams(); + }); + it(`should create index template with given parameters in default namespace`, () => { + dataStreamAdapter.getIndexTemplateFields = jest.fn().mockReturnValue({ + index_patterns: ['.internal.alerts-test.alerts-default-*'], + rollover_alias: '.alerts-test.alerts-default', + }); + expect( getIndexTemplate({ kibanaVersion: '8.6.1', @@ -80,11 +99,17 @@ describe('getIndexTemplate', () => { namespace: 'default', componentTemplateRefs: ['mappings1', 'framework-mappings'], totalFieldsLimit: 2500, + dataStreamAdapter, }) ).toEqual(IndexTemplate()); }); it(`should create index template with given parameters in custom namespace`, () => { + dataStreamAdapter.getIndexTemplateFields = jest.fn().mockReturnValue({ + index_patterns: ['.internal.alerts-test.alerts-another-space-*'], + rollover_alias: '.alerts-test.alerts-another-space', + }); + expect( getIndexTemplate({ kibanaVersion: '8.6.1', @@ -99,8 +124,9 @@ describe('getIndexTemplate', () => { namespace: 'another-space', componentTemplateRefs: ['mappings1', 'framework-mappings'], totalFieldsLimit: 2500, + dataStreamAdapter, }) - ).toEqual(IndexTemplate('another-space')); + ).toEqual(IndexTemplate('another-space', useDataStream)); }); }); @@ -164,7 +190,8 @@ describe('createOrUpdateIndexTemplate', () => { ).rejects.toThrowErrorMatchingInlineSnapshot(`"foo"`); expect(logger.error).toHaveBeenCalledWith( - `Error installing index template .alerts-test.alerts-default-index-template - foo` + `Error installing index template .alerts-test.alerts-default-index-template - foo`, + expect.any(Error) ); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(4); }); @@ -182,7 +209,8 @@ describe('createOrUpdateIndexTemplate', () => { ).rejects.toThrowErrorMatchingInlineSnapshot(`"generic error"`); expect(logger.error).toHaveBeenCalledWith( - `Error installing index template .alerts-test.alerts-default-index-template - generic error` + `Error installing index template .alerts-test.alerts-default-index-template - generic error`, + expect.any(Error) ); }); @@ -197,7 +225,8 @@ describe('createOrUpdateIndexTemplate', () => { }); expect(logger.error).toHaveBeenCalledWith( - `Failed to simulate index template mappings for .alerts-test.alerts-default-index-template; not applying mappings - simulate error` + `Failed to simulate index template mappings for .alerts-test.alerts-default-index-template; not applying mappings - simulate error`, + expect.any(Error) ); expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); }); diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_index_template.ts b/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_index_template.ts index a17fad2d875ed..30ee06a1ddda0 100644 --- a/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_index_template.ts +++ b/x-pack/plugins/alerting/server/alerts_service/lib/create_or_update_index_template.ts @@ -14,6 +14,7 @@ import { Logger, ElasticsearchClient } from '@kbn/core/server'; import { isEmpty } from 'lodash'; import { IIndexPatternString } from '../resource_installer_utils'; import { retryTransientEsErrors } from './retry_transient_es_errors'; +import { DataStreamAdapter } from './data_stream_adapter'; interface GetIndexTemplateOpts { componentTemplateRefs: string[]; @@ -22,6 +23,7 @@ interface GetIndexTemplateOpts { kibanaVersion: string; namespace: string; totalFieldsLimit: number; + dataStreamAdapter: DataStreamAdapter; } export const getIndexTemplate = ({ @@ -31,6 +33,7 @@ export const getIndexTemplate = ({ kibanaVersion, namespace, totalFieldsLimit, + dataStreamAdapter, }: GetIndexTemplateOpts): IndicesPutIndexTemplateRequest => { const indexMetadata: Metadata = { kibana: { @@ -40,19 +43,31 @@ export const getIndexTemplate = ({ namespace, }; + const dataStreamFields = dataStreamAdapter.getIndexTemplateFields( + indexPatterns.alias, + indexPatterns.pattern + ); + + const indexLifecycle = { + name: ilmPolicyName, + rollover_alias: dataStreamFields.rollover_alias, + }; + return { name: indexPatterns.template, body: { - index_patterns: [indexPatterns.pattern], + ...(dataStreamFields.data_stream ? { data_stream: dataStreamFields.data_stream } : {}), + index_patterns: dataStreamFields.index_patterns, composed_of: componentTemplateRefs, template: { settings: { auto_expand_replicas: '0-1', hidden: true, - 'index.lifecycle': { - name: ilmPolicyName, - rollover_alias: indexPatterns.alias, - }, + ...(dataStreamAdapter.isUsingDataStreams() + ? {} + : { + 'index.lifecycle': indexLifecycle, + }), 'index.mapping.total_fields.limit': totalFieldsLimit, }, mappings: { @@ -107,7 +122,8 @@ export const createOrUpdateIndexTemplate = async ({ mappings = simulateResponse.template.mappings; } catch (err) { logger.error( - `Failed to simulate index template mappings for ${template.name}; not applying mappings - ${err.message}` + `Failed to simulate index template mappings for ${template.name}; not applying mappings - ${err.message}`, + err ); return; } @@ -123,7 +139,7 @@ export const createOrUpdateIndexTemplate = async ({ logger, }); } catch (err) { - logger.error(`Error installing index template ${template.name} - ${err.message}`); + logger.error(`Error installing index template ${template.name} - ${err.message}`, err); throw err; } }; diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.mock.ts b/x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.mock.ts new file mode 100644 index 0000000000000..8de9f7bcc1731 --- /dev/null +++ b/x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.mock.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 { DataStreamAdapter, GetDataStreamAdapterOpts } from './data_stream_adapter'; + +export function createDataStreamAdapterMock(opts?: GetDataStreamAdapterOpts): DataStreamAdapter { + return { + isUsingDataStreams: jest.fn().mockReturnValue(false), + getIndexTemplateFields: jest.fn().mockReturnValue({ + index_patterns: ['index-pattern'], + }), + createStream: jest.fn(), + }; +} diff --git a/x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts b/x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts new file mode 100644 index 0000000000000..21091464a68b1 --- /dev/null +++ b/x-pack/plugins/alerting/server/alerts_service/lib/data_stream_adapter.ts @@ -0,0 +1,226 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// eslint-disable-next-line max-classes-per-file +import { + CreateConcreteWriteIndexOpts, + ConcreteIndexInfo, + updateIndexMappings, +} from './create_concrete_write_index'; +import { retryTransientEsErrors } from './retry_transient_es_errors'; + +export interface DataStreamAdapter { + isUsingDataStreams(): boolean; + getIndexTemplateFields(alias: string, pattern: string): IndexTemplateFields; + createStream(opts: CreateConcreteWriteIndexOpts): Promise; +} + +export interface BulkOpProperties { + require_alias: boolean; +} + +export interface IndexTemplateFields { + data_stream?: { hidden: true }; + index_patterns: string[]; + rollover_alias?: string; +} + +export interface GetDataStreamAdapterOpts { + useDataStreamForAlerts: boolean; +} + +export function getDataStreamAdapter(opts: GetDataStreamAdapterOpts): DataStreamAdapter { + if (opts.useDataStreamForAlerts) { + return new DataStreamImplementation(); + } else { + return new AliasImplementation(); + } +} + +// implementation using data streams +class DataStreamImplementation implements DataStreamAdapter { + isUsingDataStreams(): boolean { + return true; + } + + getIndexTemplateFields(alias: string, pattern: string): IndexTemplateFields { + return { + data_stream: { hidden: true }, + index_patterns: [alias], + }; + } + + async createStream(opts: CreateConcreteWriteIndexOpts): Promise { + return createDataStream(opts); + } +} + +// implementation using aliases and backing indices +class AliasImplementation implements DataStreamAdapter { + isUsingDataStreams(): boolean { + return false; + } + + getIndexTemplateFields(alias: string, pattern: string): IndexTemplateFields { + return { + index_patterns: [pattern], + rollover_alias: alias, + }; + } + + async createStream(opts: CreateConcreteWriteIndexOpts): Promise { + return createAliasStream(opts); + } +} + +async function createDataStream(opts: CreateConcreteWriteIndexOpts): Promise { + const { logger, esClient, indexPatterns, totalFieldsLimit } = opts; + logger.info(`Creating data stream - ${indexPatterns.alias}`); + + // check if data stream exists + let dataStreamExists = false; + try { + const response = await retryTransientEsErrors( + () => esClient.indices.getDataStream({ name: indexPatterns.alias, expand_wildcards: 'all' }), + { logger } + ); + dataStreamExists = response.data_streams.length > 0; + } catch (error) { + if (error?.statusCode !== 404) { + logger.error(`Error fetching data stream for ${indexPatterns.alias} - ${error.message}`); + throw error; + } + } + + // if a data stream exists, update the underlying mapping + if (dataStreamExists) { + await updateIndexMappings({ + logger, + esClient, + totalFieldsLimit, + concreteIndices: [ + { alias: indexPatterns.alias, index: indexPatterns.alias, isWriteIndex: true }, + ], + }); + } else { + try { + await retryTransientEsErrors( + () => + esClient.indices.createDataStream({ + name: indexPatterns.alias, + }), + { logger } + ); + } catch (error) { + if (error?.meta?.body?.error?.type !== 'resource_already_exists_exception') { + logger.error(`Error creating data stream ${indexPatterns.alias} - ${error.message}`); + throw error; + } + } + } +} + +async function createAliasStream(opts: CreateConcreteWriteIndexOpts): Promise { + const { logger, esClient, indexPatterns, totalFieldsLimit } = opts; + logger.info(`Creating concrete write index - ${indexPatterns.name}`); + + // check if a concrete write index already exists + let concreteIndices: ConcreteIndexInfo[] = []; + try { + // Specify both the index pattern for the backing indices and their aliases + // The alias prevents the request from finding other namespaces that could match the -* pattern + const response = await retryTransientEsErrors( + () => + esClient.indices.getAlias({ + index: indexPatterns.pattern, + name: indexPatterns.basePattern, + }), + { logger } + ); + + concreteIndices = Object.entries(response).flatMap(([index, { aliases }]) => + Object.entries(aliases).map(([aliasName, aliasProperties]) => ({ + index, + alias: aliasName, + isWriteIndex: aliasProperties.is_write_index ?? false, + })) + ); + + logger.debug( + `Found ${concreteIndices.length} concrete indices for ${ + indexPatterns.name + } - ${JSON.stringify(concreteIndices)}` + ); + } catch (error) { + // 404 is expected if no concrete write indices have been created + if (error.statusCode !== 404) { + logger.error( + `Error fetching concrete indices for ${indexPatterns.pattern} pattern - ${error.message}` + ); + throw error; + } + } + + let concreteWriteIndicesExist = false; + // if a concrete write index already exists, update the underlying mapping + if (concreteIndices.length > 0) { + await updateIndexMappings({ logger, esClient, totalFieldsLimit, concreteIndices }); + + const concreteIndicesExist = concreteIndices.some( + (index) => index.alias === indexPatterns.alias + ); + concreteWriteIndicesExist = concreteIndices.some( + (index) => index.alias === indexPatterns.alias && index.isWriteIndex + ); + + // If there are some concrete indices but none of them are the write index, we'll throw an error + // because one of the existing indices should have been the write target. + if (concreteIndicesExist && !concreteWriteIndicesExist) { + throw new Error( + `Indices matching pattern ${indexPatterns.pattern} exist but none are set as the write index for alias ${indexPatterns.alias}` + ); + } + } + + // check if a concrete write index already exists + if (!concreteWriteIndicesExist) { + try { + await retryTransientEsErrors( + () => + esClient.indices.create({ + index: indexPatterns.name, + body: { + aliases: { + [indexPatterns.alias]: { + is_write_index: true, + }, + }, + }, + }), + { logger } + ); + } catch (error) { + logger.error(`Error creating concrete write index - ${error.message}`); + // If the index already exists and it's the write index for the alias, + // something else created it so suppress the error. If it's not the write + // index, that's bad, throw an error. + if (error?.meta?.body?.error?.type === 'resource_already_exists_exception') { + const existingIndices = await retryTransientEsErrors( + () => esClient.indices.get({ index: indexPatterns.name }), + { logger } + ); + if (!existingIndices[indexPatterns.name]?.aliases?.[indexPatterns.alias]?.is_write_index) { + throw Error( + `Attempted to create index: ${indexPatterns.name} as the write index for alias: ${indexPatterns.alias}, but the index already exists and is not the write index for the alias` + ); + } + } else { + throw error; + } + } + } +} diff --git a/x-pack/plugins/alerting/server/index.ts b/x-pack/plugins/alerting/server/index.ts index ebfe1586031fa..ae42c665d73cf 100644 --- a/x-pack/plugins/alerting/server/index.ts +++ b/x-pack/plugins/alerting/server/index.ts @@ -32,6 +32,7 @@ export type { ExecutorType, IRuleTypeAlerts, GetViewInAppRelativeUrlFnOpts, + DataStreamAdapter, } from './types'; export { RuleNotifyWhen } from '../common'; export { DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT } from './config'; @@ -64,6 +65,7 @@ export { createConcreteWriteIndex, installWithTimeout, } from './alerts_service'; +export { getDataStreamAdapter } from './alerts_service/lib/data_stream_adapter'; export const plugin = (initContext: PluginInitializerContext) => new AlertingPlugin(initContext); diff --git a/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts b/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts index b5fff8a84c38c..007cd4481bd7e 100644 --- a/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts +++ b/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts @@ -7,6 +7,7 @@ import { eventLoggerMock } from '@kbn/event-log-plugin/server/event_logger.mock'; import { IEvent, SAVED_OBJECT_REL_PRIMARY } from '@kbn/event-log-plugin/server'; +import { ActionsCompletion } from '@kbn/alerting-state-types'; import { AlertingEventLogger, RuleContextOpts, @@ -19,7 +20,6 @@ import { } from './alerting_event_logger'; import { UntypedNormalizedRuleType } from '../../rule_type_registry'; import { - ActionsCompletion, RecoveredActionGroup, RuleExecutionStatusErrorReasons, RuleExecutionStatusWarningReasons, diff --git a/x-pack/plugins/alerting/server/lib/last_run_status.test.ts b/x-pack/plugins/alerting/server/lib/last_run_status.test.ts index d6b6f62b1b60a..33af749fe1e08 100644 --- a/x-pack/plugins/alerting/server/lib/last_run_status.test.ts +++ b/x-pack/plugins/alerting/server/lib/last_run_status.test.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { ActionsCompletion } from '@kbn/alerting-state-types'; import { lastRunFromState } from './last_run_status'; -import { ActionsCompletion } from '../../common'; import { RuleRunMetrics } from './rule_run_metrics_store'; import { RuleResultServiceResults, RuleResultService } from '../monitoring/rule_result_service'; diff --git a/x-pack/plugins/alerting/server/lib/last_run_status.ts b/x-pack/plugins/alerting/server/lib/last_run_status.ts index a007d8637eac0..56da93f074c27 100644 --- a/x-pack/plugins/alerting/server/lib/last_run_status.ts +++ b/x-pack/plugins/alerting/server/lib/last_run_status.ts @@ -5,10 +5,11 @@ * 2.0. */ +import { ActionsCompletion } from '@kbn/alerting-state-types'; import { RuleTaskStateAndMetrics } from '../task_runner/types'; import { getReasonFromError } from './error_with_reason'; import { getEsErrorMessage } from './errors'; -import { ActionsCompletion, RuleLastRunOutcomeOrderMap, RuleLastRunOutcomes } from '../../common'; +import { RuleLastRunOutcomeOrderMap, RuleLastRunOutcomes } from '../../common'; import { RuleLastRunOutcomeValues, RuleExecutionStatusWarningReasons, diff --git a/x-pack/plugins/alerting/server/lib/rule_execution_status.test.ts b/x-pack/plugins/alerting/server/lib/rule_execution_status.test.ts index 69c90ed812549..0210de56a6b0d 100644 --- a/x-pack/plugins/alerting/server/lib/rule_execution_status.test.ts +++ b/x-pack/plugins/alerting/server/lib/rule_execution_status.test.ts @@ -6,11 +6,8 @@ */ import { loggingSystemMock } from '@kbn/core/server/mocks'; -import { - ActionsCompletion, - RuleExecutionStatusErrorReasons, - RuleExecutionStatusWarningReasons, -} from '../types'; +import { ActionsCompletion } from '@kbn/alerting-state-types'; +import { RuleExecutionStatusErrorReasons, RuleExecutionStatusWarningReasons } from '../types'; import { executionStatusFromState, executionStatusFromError, diff --git a/x-pack/plugins/alerting/server/lib/rule_execution_status.ts b/x-pack/plugins/alerting/server/lib/rule_execution_status.ts index fbcf5d9ec5f2a..43ab9e2153a94 100644 --- a/x-pack/plugins/alerting/server/lib/rule_execution_status.ts +++ b/x-pack/plugins/alerting/server/lib/rule_execution_status.ts @@ -6,6 +6,7 @@ */ import { Logger } from '@kbn/core/server'; +import { ActionsCompletion } from '@kbn/alerting-state-types'; import { RuleExecutionStatus, RuleExecutionStatusValues, @@ -16,7 +17,7 @@ import { } from '../types'; import { getReasonFromError } from './error_with_reason'; import { getEsErrorMessage } from './errors'; -import { ActionsCompletion, RuleExecutionStatuses } from '../../common'; +import { RuleExecutionStatuses } from '../../common'; import { translations } from '../constants/translations'; import { RuleTaskStateAndMetrics } from '../task_runner/types'; import { RuleRunMetrics } from './rule_run_metrics_store'; diff --git a/x-pack/plugins/alerting/server/lib/rule_run_metrics_store.test.ts b/x-pack/plugins/alerting/server/lib/rule_run_metrics_store.test.ts index a042df442b787..8f2410480cc6f 100644 --- a/x-pack/plugins/alerting/server/lib/rule_run_metrics_store.test.ts +++ b/x-pack/plugins/alerting/server/lib/rule_run_metrics_store.test.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { ActionsCompletion } from '@kbn/alerting-state-types'; import { RuleRunMetricsStore } from './rule_run_metrics_store'; -import { ActionsCompletion } from '../types'; describe('RuleRunMetricsStore', () => { const ruleRunMetricsStore = new RuleRunMetricsStore(); diff --git a/x-pack/plugins/alerting/server/lib/rule_run_metrics_store.ts b/x-pack/plugins/alerting/server/lib/rule_run_metrics_store.ts index db83aeb7a63d6..14879e1558ba6 100644 --- a/x-pack/plugins/alerting/server/lib/rule_run_metrics_store.ts +++ b/x-pack/plugins/alerting/server/lib/rule_run_metrics_store.ts @@ -6,7 +6,7 @@ */ import { set } from '@kbn/safer-lodash-set'; -import { ActionsCompletion } from '../types'; +import { ActionsCompletion } from '@kbn/alerting-state-types'; import { ActionsConfigMap } from './get_actions_config_map'; import { SearchMetrics } from './types'; diff --git a/x-pack/plugins/alerting/server/lib/types.test.ts b/x-pack/plugins/alerting/server/lib/types.test.ts deleted file mode 100644 index b3f61a0f2172c..0000000000000 --- a/x-pack/plugins/alerting/server/lib/types.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { DateFromString } from './types'; -import { right, isLeft } from 'fp-ts/lib/Either'; - -describe('DateFromString', () => { - test('validated and parses a string into a Date', () => { - const date = new Date(1973, 10, 30); - expect(DateFromString.decode(date.toISOString())).toEqual(right(date)); - }); - - test('validated and returns a failure for an actual Date', () => { - const date = new Date(1973, 10, 30); - expect(isLeft(DateFromString.decode(date))).toEqual(true); - }); - - test('validated and returns a failure for an invalid Date string', () => { - expect(isLeft(DateFromString.decode('1234-23-45'))).toEqual(true); - }); - - test('validated and returns a failure for a null value', () => { - expect(isLeft(DateFromString.decode(null))).toEqual(true); - }); -}); diff --git a/x-pack/plugins/alerting/server/lib/types.ts b/x-pack/plugins/alerting/server/lib/types.ts index 173ba1119a72a..aa5c13c3fb564 100644 --- a/x-pack/plugins/alerting/server/lib/types.ts +++ b/x-pack/plugins/alerting/server/lib/types.ts @@ -5,29 +5,9 @@ * 2.0. */ -import * as t from 'io-ts'; -import { either } from 'fp-ts/lib/Either'; import { Rule } from '../types'; import { RuleRunMetrics } from './rule_run_metrics_store'; -// represents a Date from an ISO string -export const DateFromString = new t.Type( - 'DateFromString', - // detect the type - (value): value is Date => value instanceof Date, - (valueToDecode, context) => - either.chain( - // validate this is a string - t.string.validate(valueToDecode, context), - // decode - (value) => { - const decoded = new Date(value); - return isNaN(decoded.getTime()) ? t.failure(valueToDecode, context) : t.success(decoded); - } - ), - (valueToEncode) => valueToEncode.toISOString() -); - export type RuleInfo = Pick & { spaceId: string }; export interface LogSearchMetricsOpts { diff --git a/x-pack/plugins/alerting/server/mocks.ts b/x-pack/plugins/alerting/server/mocks.ts index 9aa7209ea5fa1..ab81e472f938b 100644 --- a/x-pack/plugins/alerting/server/mocks.ts +++ b/x-pack/plugins/alerting/server/mocks.ts @@ -35,6 +35,7 @@ const createSetupMock = () => { enabled: jest.fn(), getContextInitializationPromise: jest.fn(), }, + getDataStreamAdapter: jest.fn(), }; return mock; }; @@ -190,3 +191,5 @@ export const alertsMock = { export const ruleMonitoringServiceMock = { create: createRuleMonitoringServiceMock }; export const ruleLastRunServiceMock = { create: createRuleLastRunServiceMock }; + +export { createDataStreamAdapterMock } from './alerts_service/lib/data_stream_adapter.mock'; diff --git a/x-pack/plugins/alerting/server/plugin.test.ts b/x-pack/plugins/alerting/server/plugin.test.ts index 859e69b6da131..b355ecbf370a5 100644 --- a/x-pack/plugins/alerting/server/plugin.test.ts +++ b/x-pack/plugins/alerting/server/plugin.test.ts @@ -36,30 +36,7 @@ jest.mock('./alerts_service/alerts_service', () => ({ })); import { SharePluginStart } from '@kbn/share-plugin/server'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; - -const generateAlertingConfig = (): AlertingConfig => ({ - healthCheck: { - interval: '5m', - }, - enableFrameworkAlerts: false, - invalidateApiKeysTask: { - interval: '5m', - removalDelay: '1h', - }, - maxEphemeralActionsPerAlert: 10, - cancelAlertsOnRuleTimeout: true, - rules: { - minimumScheduleInterval: { value: '1m', enforce: false }, - run: { - actions: { - max: 1000, - }, - alerts: { - max: 1000, - }, - }, - }, -}); +import { generateAlertingConfig } from './test_utils'; const sampleRuleType: RuleType = { id: 'test', @@ -78,329 +55,344 @@ const sampleRuleType: RuleType { - describe('setup()', () => { - const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup(); - const setupMocks = coreMock.createSetup(); - const mockPlugins = { - licensing: licensingMock.createSetup(), - encryptedSavedObjects: encryptedSavedObjectsSetup, - taskManager: taskManagerMock.createSetup(), - eventLog: eventLogServiceMock.create(), - actions: actionsMock.createSetup(), - statusService: statusServiceMock.createSetupContract(), - monitoringCollection: monitoringCollectionMock.createSetup(), - data: dataPluginMock.createSetupContract() as unknown as DataPluginSetup, - features: featuresPluginMock.createSetup(), - unifiedSearch: autocompletePluginMock.createSetupContract(), - }; - - let plugin: AlertingPlugin; - - beforeEach(() => jest.clearAllMocks()); - - it('should log warning when Encrypted Saved Objects plugin is missing encryption key', async () => { - const context = coreMock.createPluginInitializerContext( - generateAlertingConfig() - ); - plugin = new AlertingPlugin(context); - - // need await to test number of calls of setupMocks.status.set, because it is under async function which awaiting core.getStartServices() - await plugin.setup(setupMocks, mockPlugins); - - expect(setupMocks.status.set).toHaveBeenCalledTimes(1); - expect(encryptedSavedObjectsSetup.canEncrypt).toEqual(false); - expect(context.logger.get().warn).toHaveBeenCalledWith( - 'APIs are disabled because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' - ); - }); - - it('should create usage counter if usageCollection plugin is defined', async () => { - const context = coreMock.createPluginInitializerContext( - generateAlertingConfig() - ); - plugin = new AlertingPlugin(context); + for (const useDataStreamForAlerts of [false, true]) { + const label = useDataStreamForAlerts ? 'data streams' : 'aliases'; - const usageCollectionSetup = createUsageCollectionSetupMock(); - - // need await to test number of calls of setupMocks.status.set, because it is under async function which awaiting core.getStartServices() - await plugin.setup(setupMocks, { ...mockPlugins, usageCollection: usageCollectionSetup }); + describe(`using ${label} for alert indices`, () => { + describe('setup()', () => { + const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup(); + const setupMocks = coreMock.createSetup(); + const mockPlugins = { + licensing: licensingMock.createSetup(), + encryptedSavedObjects: encryptedSavedObjectsSetup, + taskManager: taskManagerMock.createSetup(), + eventLog: eventLogServiceMock.create(), + actions: actionsMock.createSetup(), + statusService: statusServiceMock.createSetupContract(), + monitoringCollection: monitoringCollectionMock.createSetup(), + data: dataPluginMock.createSetupContract() as unknown as DataPluginSetup, + features: featuresPluginMock.createSetup(), + unifiedSearch: autocompletePluginMock.createSetupContract(), + // serverless setup is currently empty, and there is no mock + ...(useDataStreamForAlerts ? { serverless: {} } : {}), + }; - expect(usageCollectionSetup.createUsageCounter).toHaveBeenCalled(); - expect(usageCollectionSetup.registerCollector).toHaveBeenCalled(); - }); + let plugin: AlertingPlugin; - it('should initialize AlertsService if enableFrameworkAlerts config is true', async () => { - const context = coreMock.createPluginInitializerContext({ - ...generateAlertingConfig(), - enableFrameworkAlerts: true, - }); - plugin = new AlertingPlugin(context); + beforeEach(() => jest.clearAllMocks()); - // need await to test number of calls of setupMocks.status.set, because it is under async function which awaiting core.getStartServices() - const setupContract = await plugin.setup(setupMocks, mockPlugins); + it('should log warning when Encrypted Saved Objects plugin is missing encryption key', async () => { + const context = coreMock.createPluginInitializerContext( + generateAlertingConfig() + ); + plugin = new AlertingPlugin(context); - expect(AlertsService).toHaveBeenCalled(); + plugin.setup(setupMocks, mockPlugins); + await waitForSetupComplete(setupMocks); - expect(setupContract.frameworkAlerts.enabled()).toEqual(true); - }); + expect(setupMocks.status.set).toHaveBeenCalledTimes(1); + expect(encryptedSavedObjectsSetup.canEncrypt).toEqual(false); + expect(context.logger.get().warn).toHaveBeenCalledWith( + 'APIs are disabled because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' + ); + }); - it(`exposes configured minimumScheduleInterval()`, async () => { - const context = coreMock.createPluginInitializerContext( - generateAlertingConfig() - ); - plugin = new AlertingPlugin(context); + it('should create usage counter if usageCollection plugin is defined', async () => { + const context = coreMock.createPluginInitializerContext( + generateAlertingConfig() + ); + plugin = new AlertingPlugin(context); - const setupContract = await plugin.setup(setupMocks, mockPlugins); + const usageCollectionSetup = createUsageCollectionSetupMock(); - expect(setupContract.getConfig()).toEqual({ - isUsingSecurity: false, - minimumScheduleInterval: { value: '1m', enforce: false }, - }); + // need await to test number of calls of setupMocks.status.set, because it is under async function which awaiting core.getStartServices() + plugin.setup(setupMocks, { ...mockPlugins, usageCollection: usageCollectionSetup }); + await waitForSetupComplete(setupMocks); - expect(setupContract.frameworkAlerts.enabled()).toEqual(false); - }); + expect(usageCollectionSetup.createUsageCounter).toHaveBeenCalled(); + expect(usageCollectionSetup.registerCollector).toHaveBeenCalled(); + }); - describe('registerType()', () => { - let setup: PluginSetupContract; - beforeEach(async () => { - const context = coreMock.createPluginInitializerContext( - generateAlertingConfig() - ); - plugin = new AlertingPlugin(context); - setup = await plugin.setup(setupMocks, mockPlugins); - }); + it('should initialize AlertsService if enableFrameworkAlerts config is true', async () => { + const context = coreMock.createPluginInitializerContext({ + ...generateAlertingConfig(), + enableFrameworkAlerts: true, + }); + plugin = new AlertingPlugin(context); - it('should throw error when license type is invalid', async () => { - expect(() => - setup.registerType({ - ...sampleRuleType, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - minimumLicenseRequired: 'foo' as any, - }) - ).toThrowErrorMatchingInlineSnapshot(`"\\"foo\\" is not a valid license type"`); - }); + // need await to test number of calls of setupMocks.status.set, because it is under async function which awaiting core.getStartServices() + const setupContract = plugin.setup(setupMocks, mockPlugins); + await waitForSetupComplete(setupMocks); - it('should not throw when license type is gold', async () => { - setup.registerType({ - ...sampleRuleType, - minimumLicenseRequired: 'gold', - }); - }); + expect(AlertsService).toHaveBeenCalled(); - it('should not throw when license type is basic', async () => { - setup.registerType({ - ...sampleRuleType, - minimumLicenseRequired: 'basic', + expect(setupContract.frameworkAlerts.enabled()).toEqual(true); }); - }); - - it('should apply default config value for ruleTaskTimeout if no value is specified', async () => { - const ruleType = { - ...sampleRuleType, - minimumLicenseRequired: 'basic', - } as RuleType; - await setup.registerType(ruleType); - expect(ruleType.ruleTaskTimeout).toBe('5m'); - }); - it('should apply value for ruleTaskTimeout if specified', async () => { - const ruleType = { - ...sampleRuleType, - minimumLicenseRequired: 'basic', - ruleTaskTimeout: '20h', - } as RuleType; - await setup.registerType(ruleType); - expect(ruleType.ruleTaskTimeout).toBe('20h'); - }); - - it('should apply default config value for cancelAlertsOnRuleTimeout if no value is specified', async () => { - const ruleType = { - ...sampleRuleType, - minimumLicenseRequired: 'basic', - } as RuleType; - await setup.registerType(ruleType); - expect(ruleType.cancelAlertsOnRuleTimeout).toBe(true); - }); + it(`exposes configured minimumScheduleInterval()`, async () => { + const context = coreMock.createPluginInitializerContext( + generateAlertingConfig() + ); + plugin = new AlertingPlugin(context); - it('should apply value for cancelAlertsOnRuleTimeout if specified', async () => { - const ruleType = { - ...sampleRuleType, - minimumLicenseRequired: 'basic', - cancelAlertsOnRuleTimeout: false, - } as RuleType; - await setup.registerType(ruleType); - expect(ruleType.cancelAlertsOnRuleTimeout).toBe(false); - }); - }); - }); + const setupContract = plugin.setup(setupMocks, mockPlugins); + await waitForSetupComplete(setupMocks); - describe('start()', () => { - describe('getRulesClientWithRequest()', () => { - it('throws error when encryptedSavedObjects plugin is missing encryption key', async () => { - const context = coreMock.createPluginInitializerContext( - generateAlertingConfig() - ); - const plugin = new AlertingPlugin(context); + expect(setupContract.getConfig()).toEqual({ + isUsingSecurity: false, + minimumScheduleInterval: { value: '1m', enforce: false }, + }); - const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup(); - plugin.setup(coreMock.createSetup(), { - licensing: licensingMock.createSetup(), - encryptedSavedObjects: encryptedSavedObjectsSetup, - taskManager: taskManagerMock.createSetup(), - eventLog: eventLogServiceMock.create(), - actions: actionsMock.createSetup(), - statusService: statusServiceMock.createSetupContract(), - monitoringCollection: monitoringCollectionMock.createSetup(), - data: dataPluginMock.createSetupContract() as unknown as DataPluginSetup, - features: featuresPluginMock.createSetup(), - unifiedSearch: autocompletePluginMock.createSetupContract(), + expect(setupContract.frameworkAlerts.enabled()).toEqual(false); }); - const startContract = plugin.start(coreMock.createStart(), { - actions: actionsMock.createStart(), - encryptedSavedObjects: encryptedSavedObjectsMock.createStart(), - features: mockFeatures(), - spaces: spacesMock.createStart(), - licensing: licensingMock.createStart(), - eventLog: eventLogMock.createStart(), - taskManager: taskManagerMock.createStart(), - data: dataPluginMock.createStartContract(), - share: {} as SharePluginStart, - dataViews: { - dataViewsServiceFactory: jest - .fn() - .mockResolvedValue(dataViewPluginMocks.createStartContract()), - getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), - } as DataViewsServerPluginStart, + describe('registerType()', () => { + let setup: PluginSetupContract; + beforeEach(async () => { + const context = coreMock.createPluginInitializerContext( + generateAlertingConfig() + ); + plugin = new AlertingPlugin(context); + setup = plugin.setup(setupMocks, mockPlugins); + await waitForSetupComplete(setupMocks); + }); + + it('should throw error when license type is invalid', async () => { + expect(() => + setup.registerType({ + ...sampleRuleType, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + minimumLicenseRequired: 'foo' as any, + }) + ).toThrowErrorMatchingInlineSnapshot(`"\\"foo\\" is not a valid license type"`); + }); + + it('should not throw when license type is gold', async () => { + setup.registerType({ + ...sampleRuleType, + minimumLicenseRequired: 'gold', + }); + }); + + it('should not throw when license type is basic', async () => { + setup.registerType({ + ...sampleRuleType, + minimumLicenseRequired: 'basic', + }); + }); + + it('should apply default config value for ruleTaskTimeout if no value is specified', async () => { + const ruleType = { + ...sampleRuleType, + minimumLicenseRequired: 'basic', + } as RuleType; + await setup.registerType(ruleType); + expect(ruleType.ruleTaskTimeout).toBe('5m'); + }); + + it('should apply value for ruleTaskTimeout if specified', async () => { + const ruleType = { + ...sampleRuleType, + minimumLicenseRequired: 'basic', + ruleTaskTimeout: '20h', + } as RuleType; + await setup.registerType(ruleType); + expect(ruleType.ruleTaskTimeout).toBe('20h'); + }); + + it('should apply default config value for cancelAlertsOnRuleTimeout if no value is specified', async () => { + const ruleType = { + ...sampleRuleType, + minimumLicenseRequired: 'basic', + } as RuleType; + await setup.registerType(ruleType); + expect(ruleType.cancelAlertsOnRuleTimeout).toBe(true); + }); + + it('should apply value for cancelAlertsOnRuleTimeout if specified', async () => { + const ruleType = { + ...sampleRuleType, + minimumLicenseRequired: 'basic', + cancelAlertsOnRuleTimeout: false, + } as RuleType; + await setup.registerType(ruleType); + expect(ruleType.cancelAlertsOnRuleTimeout).toBe(false); + }); }); - - expect(encryptedSavedObjectsSetup.canEncrypt).toEqual(false); - expect(() => - startContract.getRulesClientWithRequest({} as KibanaRequest) - ).toThrowErrorMatchingInlineSnapshot( - `"Unable to create alerts client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` - ); }); - it(`doesn't throw error when encryptedSavedObjects plugin has encryption key`, async () => { - const context = coreMock.createPluginInitializerContext( - generateAlertingConfig() - ); - const plugin = new AlertingPlugin(context); - - const encryptedSavedObjectsSetup = { - ...encryptedSavedObjectsMock.createSetup(), - canEncrypt: true, - }; - plugin.setup(coreMock.createSetup(), { - licensing: licensingMock.createSetup(), - encryptedSavedObjects: encryptedSavedObjectsSetup, - taskManager: taskManagerMock.createSetup(), - eventLog: eventLogServiceMock.create(), - actions: actionsMock.createSetup(), - statusService: statusServiceMock.createSetupContract(), - monitoringCollection: monitoringCollectionMock.createSetup(), - data: dataPluginMock.createSetupContract() as unknown as DataPluginSetup, - features: featuresPluginMock.createSetup(), - unifiedSearch: autocompletePluginMock.createSetupContract(), - }); - - const startContract = plugin.start(coreMock.createStart(), { - actions: actionsMock.createStart(), - encryptedSavedObjects: encryptedSavedObjectsMock.createStart(), - features: mockFeatures(), - spaces: spacesMock.createStart(), - licensing: licensingMock.createStart(), - eventLog: eventLogMock.createStart(), - taskManager: taskManagerMock.createStart(), - data: dataPluginMock.createStartContract(), - share: {} as SharePluginStart, - dataViews: { - dataViewsServiceFactory: jest - .fn() - .mockResolvedValue(dataViewPluginMocks.createStartContract()), - getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), - } as DataViewsServerPluginStart, + describe('start()', () => { + describe('getRulesClientWithRequest()', () => { + it('throws error when encryptedSavedObjects plugin is missing encryption key', async () => { + const context = coreMock.createPluginInitializerContext( + generateAlertingConfig() + ); + const plugin = new AlertingPlugin(context); + + const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup(); + plugin.setup(coreMock.createSetup(), { + licensing: licensingMock.createSetup(), + encryptedSavedObjects: encryptedSavedObjectsSetup, + taskManager: taskManagerMock.createSetup(), + eventLog: eventLogServiceMock.create(), + actions: actionsMock.createSetup(), + statusService: statusServiceMock.createSetupContract(), + monitoringCollection: monitoringCollectionMock.createSetup(), + data: dataPluginMock.createSetupContract() as unknown as DataPluginSetup, + features: featuresPluginMock.createSetup(), + unifiedSearch: autocompletePluginMock.createSetupContract(), + ...(useDataStreamForAlerts ? { serverless: {} } : {}), + }); + + const startContract = plugin.start(coreMock.createStart(), { + actions: actionsMock.createStart(), + encryptedSavedObjects: encryptedSavedObjectsMock.createStart(), + features: mockFeatures(), + spaces: spacesMock.createStart(), + licensing: licensingMock.createStart(), + eventLog: eventLogMock.createStart(), + taskManager: taskManagerMock.createStart(), + data: dataPluginMock.createStartContract(), + share: {} as SharePluginStart, + dataViews: { + dataViewsServiceFactory: jest + .fn() + .mockResolvedValue(dataViewPluginMocks.createStartContract()), + getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), + } as DataViewsServerPluginStart, + }); + + expect(encryptedSavedObjectsSetup.canEncrypt).toEqual(false); + expect(() => + startContract.getRulesClientWithRequest({} as KibanaRequest) + ).toThrowErrorMatchingInlineSnapshot( + `"Unable to create alerts client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."` + ); + }); + + it(`doesn't throw error when encryptedSavedObjects plugin has encryption key`, async () => { + const context = coreMock.createPluginInitializerContext( + generateAlertingConfig() + ); + const plugin = new AlertingPlugin(context); + + const encryptedSavedObjectsSetup = { + ...encryptedSavedObjectsMock.createSetup(), + canEncrypt: true, + }; + plugin.setup(coreMock.createSetup(), { + licensing: licensingMock.createSetup(), + encryptedSavedObjects: encryptedSavedObjectsSetup, + taskManager: taskManagerMock.createSetup(), + eventLog: eventLogServiceMock.create(), + actions: actionsMock.createSetup(), + statusService: statusServiceMock.createSetupContract(), + monitoringCollection: monitoringCollectionMock.createSetup(), + data: dataPluginMock.createSetupContract() as unknown as DataPluginSetup, + features: featuresPluginMock.createSetup(), + unifiedSearch: autocompletePluginMock.createSetupContract(), + ...(useDataStreamForAlerts ? { serverless: {} } : {}), + }); + + const startContract = plugin.start(coreMock.createStart(), { + actions: actionsMock.createStart(), + encryptedSavedObjects: encryptedSavedObjectsMock.createStart(), + features: mockFeatures(), + spaces: spacesMock.createStart(), + licensing: licensingMock.createStart(), + eventLog: eventLogMock.createStart(), + taskManager: taskManagerMock.createStart(), + data: dataPluginMock.createStartContract(), + share: {} as SharePluginStart, + dataViews: { + dataViewsServiceFactory: jest + .fn() + .mockResolvedValue(dataViewPluginMocks.createStartContract()), + getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), + } as DataViewsServerPluginStart, + }); + + const fakeRequest = { + headers: {}, + getBasePath: () => '', + path: '/', + route: { settings: {} }, + url: { + href: '/', + }, + raw: { + req: { + url: '/', + }, + }, + getSavedObjectsClient: jest.fn(), + } as unknown as KibanaRequest; + startContract.getRulesClientWithRequest(fakeRequest); + }); }); - const fakeRequest = { - headers: {}, - getBasePath: () => '', - path: '/', - route: { settings: {} }, - url: { - href: '/', - }, - raw: { - req: { - url: '/', + test(`exposes getAlertingAuthorizationWithRequest()`, async () => { + const context = coreMock.createPluginInitializerContext( + generateAlertingConfig() + ); + const plugin = new AlertingPlugin(context); + + const encryptedSavedObjectsSetup = { + ...encryptedSavedObjectsMock.createSetup(), + canEncrypt: true, + }; + plugin.setup(coreMock.createSetup(), { + licensing: licensingMock.createSetup(), + encryptedSavedObjects: encryptedSavedObjectsSetup, + taskManager: taskManagerMock.createSetup(), + eventLog: eventLogServiceMock.create(), + actions: actionsMock.createSetup(), + statusService: statusServiceMock.createSetupContract(), + monitoringCollection: monitoringCollectionMock.createSetup(), + data: dataPluginMock.createSetupContract() as unknown as DataPluginSetup, + features: featuresPluginMock.createSetup(), + unifiedSearch: autocompletePluginMock.createSetupContract(), + ...(useDataStreamForAlerts ? { serverless: {} } : {}), + }); + + const startContract = plugin.start(coreMock.createStart(), { + actions: actionsMock.createStart(), + encryptedSavedObjects: encryptedSavedObjectsMock.createStart(), + features: mockFeatures(), + spaces: spacesMock.createStart(), + licensing: licensingMock.createStart(), + eventLog: eventLogMock.createStart(), + taskManager: taskManagerMock.createStart(), + data: dataPluginMock.createStartContract(), + share: {} as SharePluginStart, + dataViews: { + dataViewsServiceFactory: jest + .fn() + .mockResolvedValue(dataViewPluginMocks.createStartContract()), + getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), + } as DataViewsServerPluginStart, + }); + + const fakeRequest = { + headers: {}, + getBasePath: () => '', + path: '/', + route: { settings: {} }, + url: { + href: '/', }, - }, - getSavedObjectsClient: jest.fn(), - } as unknown as KibanaRequest; - startContract.getRulesClientWithRequest(fakeRequest); - }); - }); - - test(`exposes getAlertingAuthorizationWithRequest()`, async () => { - const context = coreMock.createPluginInitializerContext( - generateAlertingConfig() - ); - const plugin = new AlertingPlugin(context); - - const encryptedSavedObjectsSetup = { - ...encryptedSavedObjectsMock.createSetup(), - canEncrypt: true, - }; - plugin.setup(coreMock.createSetup(), { - licensing: licensingMock.createSetup(), - encryptedSavedObjects: encryptedSavedObjectsSetup, - taskManager: taskManagerMock.createSetup(), - eventLog: eventLogServiceMock.create(), - actions: actionsMock.createSetup(), - statusService: statusServiceMock.createSetupContract(), - monitoringCollection: monitoringCollectionMock.createSetup(), - data: dataPluginMock.createSetupContract() as unknown as DataPluginSetup, - features: featuresPluginMock.createSetup(), - unifiedSearch: autocompletePluginMock.createSetupContract(), - }); - - const startContract = plugin.start(coreMock.createStart(), { - actions: actionsMock.createStart(), - encryptedSavedObjects: encryptedSavedObjectsMock.createStart(), - features: mockFeatures(), - spaces: spacesMock.createStart(), - licensing: licensingMock.createStart(), - eventLog: eventLogMock.createStart(), - taskManager: taskManagerMock.createStart(), - data: dataPluginMock.createStartContract(), - share: {} as SharePluginStart, - dataViews: { - dataViewsServiceFactory: jest - .fn() - .mockResolvedValue(dataViewPluginMocks.createStartContract()), - getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), - } as DataViewsServerPluginStart, + raw: { + req: { + url: '/', + }, + }, + getSavedObjectsClient: jest.fn(), + } as unknown as KibanaRequest; + startContract.getAlertingAuthorizationWithRequest(fakeRequest); + }); }); - - const fakeRequest = { - headers: {}, - getBasePath: () => '', - path: '/', - route: { settings: {} }, - url: { - href: '/', - }, - raw: { - req: { - url: '/', - }, - }, - getSavedObjectsClient: jest.fn(), - } as unknown as KibanaRequest; - startContract.getAlertingAuthorizationWithRequest(fakeRequest); }); - }); + } }); function mockFeatures() { @@ -431,3 +423,22 @@ function mockFeatures() { ]); return features; } + +type CoreSetupMocks = ReturnType; + +const WaitForSetupAttempts = 10; +const WaitForSetupDelay = 200; +const WaitForSetupSeconds = (WaitForSetupAttempts * WaitForSetupDelay) / 1000; + +// wait for setup to *really* complete: waiting for calls to +// setupMocks.status.set, which needs to wait for core.getStartServices() +export async function waitForSetupComplete(setupMocks: CoreSetupMocks) { + let attempts = 0; + while (setupMocks.status.set.mock.calls.length < 1) { + attempts++; + await new Promise((resolve) => setTimeout(resolve, WaitForSetupDelay)); + if (attempts > WaitForSetupAttempts) { + throw new Error(`setupMocks.status.set was not called within ${WaitForSetupSeconds} seconds`); + } + } +} diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index dd20272b0fb68..fafd9a13925ab 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -56,6 +56,8 @@ import type { PluginSetup as UnifiedSearchServerPluginSetup } from '@kbn/unified import { PluginStart as DataPluginStart } from '@kbn/data-plugin/server'; import { MonitoringCollectionSetup } from '@kbn/monitoring-collection-plugin/server'; import { SharePluginStart } from '@kbn/share-plugin/server'; +import { ServerlessPluginSetup } from '@kbn/serverless/server'; + import { RuleTypeRegistry } from './rule_type_registry'; import { TaskRunnerFactory } from './task_runner'; import { RulesClientFactory } from './rules_client_factory'; @@ -97,6 +99,7 @@ import { } from './alerts_service'; import { rulesSettingsFeature } from './rules_settings_feature'; import { maintenanceWindowFeature } from './maintenance_window_feature'; +import { DataStreamAdapter, getDataStreamAdapter } from './alerts_service/lib/data_stream_adapter'; import { createGetAlertIndicesAliasFn, GetAlertIndicesAlias } from './lib'; export const EVENT_LOG_PROVIDER = 'alerting'; @@ -139,6 +142,7 @@ export interface PluginSetupContract { getSecurityHealth: () => Promise; getConfig: () => AlertingRulesConfig; frameworkAlerts: PublicFrameworkAlertsService; + getDataStreamAdapter: () => DataStreamAdapter; } export interface PluginStartContract { @@ -170,6 +174,7 @@ export interface AlertingPluginsSetup { data: DataPluginSetup; features: FeaturesPluginSetup; unifiedSearch: UnifiedSearchServerPluginSetup; + serverless?: ServerlessPluginSetup; } export interface AlertingPluginsStart { @@ -207,6 +212,7 @@ export class AlertingPlugin { private inMemoryMetrics: InMemoryMetrics; private alertsService: AlertsService | null; private pluginStop$: Subject; + private dataStreamAdapter?: DataStreamAdapter; constructor(initializerContext: PluginInitializerContext) { this.config = initializerContext.config.get(); @@ -231,6 +237,14 @@ export class AlertingPlugin { this.licenseState = new LicenseState(plugins.licensing.license$); this.security = plugins.security; + const useDataStreamForAlerts = !!plugins.serverless; + this.dataStreamAdapter = getDataStreamAdapter({ useDataStreamForAlerts }); + this.logger.info( + `using ${ + this.dataStreamAdapter.isUsingDataStreams() ? 'datastreams' : 'indexes and aliases' + } for persisting alerts` + ); + core.capabilities.registerProvider(() => { return { management: { @@ -266,6 +280,7 @@ export class AlertingPlugin { logger: this.logger, pluginStop$: this.pluginStop$, kibanaVersion: this.kibanaVersion, + dataStreamAdapter: this.dataStreamAdapter!, elasticsearchClientPromise: core .getStartServices() .then(([{ elasticsearch }]) => elasticsearch.client.asInternalUser), @@ -417,6 +432,7 @@ export class AlertingPlugin { return Promise.resolve(errorResult(`Framework alerts service not available`)); }, }, + getDataStreamAdapter: () => this.dataStreamAdapter!, }; } diff --git a/x-pack/plugins/alerting/server/routes/get_rule_state.test.ts b/x-pack/plugins/alerting/server/routes/get_rule_state.test.ts index 04d3704c88714..d84c6fe73b616 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_state.test.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_state.test.ts @@ -32,7 +32,7 @@ describe('getRuleStateRoute', () => { meta: { lastScheduledActions: { group: 'first_group', - date: new Date(), + date: new Date().toISOString(), }, }, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts index 42527256925f7..67fd50a965ea4 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts @@ -37,7 +37,7 @@ describe('getAlertStateRoute', () => { meta: { lastScheduledActions: { group: 'first_group', - date: new Date(), + date: new Date().toISOString(), }, }, }, diff --git a/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts b/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts index 4b2847eb16f73..ea88e2eba19bd 100644 --- a/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts +++ b/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts @@ -30,7 +30,7 @@ describe('updateRuleApiKeyRoute', () => { const [config, handler] = router.post.mock.calls[0]; - expect(config.path).toMatchInlineSnapshot(`"/internal/alerting/rule/{id}/_update_api_key"`); + expect(config.path).toMatchInlineSnapshot(`"/api/alerting/rule/{id}/_update_api_key"`); rulesClient.updateApiKey.mockResolvedValueOnce(); diff --git a/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts b/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts index 4e99b54e76af4..6ba598fe621e0 100644 --- a/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts +++ b/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts @@ -9,7 +9,7 @@ import { IRouter } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; import { ILicenseState, RuleTypeDisabledError } from '../lib'; import { verifyAccessAndContext } from './lib'; -import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types'; +import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types'; const paramSchema = schema.object({ id: schema.string(), @@ -21,7 +21,7 @@ export const updateRuleApiKeyRoute = ( ) => { router.post( { - path: `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_update_api_key`, + path: `${BASE_ALERTING_API_PATH}/rule/{id}/_update_api_key`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/rule_type_registry.test.ts b/x-pack/plugins/alerting/server/rule_type_registry.test.ts index 353435257708b..689741c7479ac 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.test.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.test.ts @@ -17,7 +17,6 @@ import { inMemoryMetricsMock } from './monitoring/in_memory_metrics.mock'; import { alertsServiceMock } from './alerts_service/alerts_service.mock'; import { schema } from '@kbn/config-schema'; import { RecoveredActionGroupId } from '../common'; -import { rawRuleSchema } from './raw_rule_schema'; const logger = loggingSystemMock.create().get(); let mockedLicenseState: jest.Mocked; @@ -437,17 +436,12 @@ describe('Create Lifecycle', () => { const registry = new RuleTypeRegistry(ruleTypeRegistryParams); registry.register(ruleType); expect(taskManager.registerTaskDefinitions).toHaveBeenCalledTimes(1); - expect(taskManager.registerTaskDefinitions.mock.calls[0]).toEqual([ - { - 'alerting:test': { - createTaskRunner: expect.any(Function), - paramsSchema: expect.any(Object), - indirectParamsSchema: rawRuleSchema, - timeout: '20m', - title: 'Test', - }, + expect(taskManager.registerTaskDefinitions.mock.calls[0][0]).toMatchObject({ + 'alerting:test': { + timeout: '20m', + title: 'Test', }, - ]); + }); }); test('shallow clones the given rule type', () => { diff --git a/x-pack/plugins/alerting/server/rule_type_registry.ts b/x-pack/plugins/alerting/server/rule_type_registry.ts index 61600bf2b0955..c0339275bcf35 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.ts @@ -13,6 +13,7 @@ import { intersection } from 'lodash'; import { Logger } from '@kbn/core/server'; import { LicensingPluginSetup } from '@kbn/licensing-plugin/server'; import { RunContext, TaskManagerSetupContract } from '@kbn/task-manager-plugin/server'; +import { stateSchemaByVersion } from '@kbn/alerting-state-types'; import { rawRuleSchema } from './raw_rule_schema'; import { TaskRunnerFactory } from './task_runner'; import { @@ -279,10 +280,12 @@ export class RuleTypeRegistry { /** stripping the typing is required in order to store the RuleTypes in a Map */ normalizedRuleType as unknown as UntypedNormalizedRuleType ); + this.taskManager.registerTaskDefinitions({ [`alerting:${ruleType.id}`]: { title: ruleType.name, timeout: ruleType.ruleTaskTimeout, + stateSchemaByVersion, createTaskRunner: (context: RunContext) => this.taskRunnerFactory.create< Params, @@ -302,6 +305,7 @@ export class RuleTypeRegistry { indirectParamsSchema: rawRuleSchema, }, }); + if (this.alertsService && ruleType.alerts) { this.alertsService.register(ruleType.alerts as IRuleTypeAlerts); } diff --git a/x-pack/plugins/alerting/server/task_runner/alert_task_instance.test.ts b/x-pack/plugins/alerting/server/task_runner/alert_task_instance.test.ts index 916d9c27a7831..93bb08a55c7d0 100644 --- a/x-pack/plugins/alerting/server/task_runner/alert_task_instance.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/alert_task_instance.test.ts @@ -41,8 +41,7 @@ const alert: SanitizedRule<{ }; describe('Alert Task Instance', () => { - test(`validates that a TaskInstance has valid Alert Task State`, () => { - const lastScheduledActionsDate = new Date(); + test(`passes-through the state object`, () => { const taskInstance: ConcreteTaskInstance = { id: uuidv4(), attempts: 0, @@ -52,129 +51,7 @@ describe('Alert Task Instance', () => { scheduledAt: new Date(), startedAt: new Date(), retryAt: new Date(Date.now() + 5 * 60 * 1000), - state: { - alertTypeState: { - some: 'value', - }, - alertInstances: { - first_instance: { - state: {}, - meta: { - lastScheduledActions: { - group: 'first_group', - date: lastScheduledActionsDate.toISOString(), - }, - }, - }, - second_instance: {}, - }, - }, - taskType: 'alerting:test', - params: { - alertId: '1', - }, - ownerId: null, - }; - - const alertTaskInsatnce: AlertTaskInstance = taskInstanceToAlertTaskInstance(taskInstance); - - expect(alertTaskInsatnce).toEqual({ - ...taskInstance, - state: { - alertTypeState: { - some: 'value', - }, - alertInstances: { - first_instance: { - state: {}, - meta: { - lastScheduledActions: { - group: 'first_group', - date: lastScheduledActionsDate, - }, - }, - }, - second_instance: {}, - }, - }, - }); - }); - - test(`throws if state is invalid`, () => { - const taskInstance: ConcreteTaskInstance = { - id: '215ee69b-1df9-428e-ab1a-ccf274f8fa5b', - attempts: 0, - status: TaskStatus.Running, - version: '123', - runAt: new Date(), - scheduledAt: new Date(), - startedAt: new Date(), - retryAt: new Date(Date.now() + 5 * 60 * 1000), - state: { - alertTypeState: { - some: 'value', - }, - alertInstances: { - first_instance: 'invalid', - second_instance: {}, - }, - }, - taskType: 'alerting:test', - params: { - alertId: '1', - }, - ownerId: null, - }; - - expect(() => taskInstanceToAlertTaskInstance(taskInstance)).toThrowErrorMatchingInlineSnapshot( - `"Task \\"215ee69b-1df9-428e-ab1a-ccf274f8fa5b\\" has invalid state at .alertInstances.first_instance"` - ); - }); - - test(`throws with Alert id when alert is present and state is invalid`, () => { - const taskInstance: ConcreteTaskInstance = { - id: '215ee69b-1df9-428e-ab1a-ccf274f8fa5b', - attempts: 0, - status: TaskStatus.Running, - version: '123', - runAt: new Date(), - scheduledAt: new Date(), - startedAt: new Date(), - retryAt: new Date(Date.now() + 5 * 60 * 1000), - state: { - alertTypeState: { - some: 'value', - }, - alertInstances: { - first_instance: 'invalid', - second_instance: {}, - }, - }, - taskType: 'alerting:test', - params: { - alertId: '1', - }, - ownerId: null, - }; - - expect(() => - taskInstanceToAlertTaskInstance(taskInstance, alert) - ).toThrowErrorMatchingInlineSnapshot( - `"Task \\"215ee69b-1df9-428e-ab1a-ccf274f8fa5b\\" (underlying Alert \\"alert-123\\") has invalid state at .alertInstances.first_instance"` - ); - }); - - test(`allows an initial empty state`, () => { - const taskInstance: ConcreteTaskInstance = { - id: uuidv4(), - attempts: 0, - status: TaskStatus.Running, - version: '123', - runAt: new Date(), - scheduledAt: new Date(), - startedAt: new Date(), - retryAt: new Date(Date.now() + 5 * 60 * 1000), - state: {}, + state: { foo: true }, taskType: 'alerting:test', params: { alertId: '1', diff --git a/x-pack/plugins/alerting/server/task_runner/alert_task_instance.ts b/x-pack/plugins/alerting/server/task_runner/alert_task_instance.ts index d831fe8c63b07..adcf228dde783 100644 --- a/x-pack/plugins/alerting/server/task_runner/alert_task_instance.ts +++ b/x-pack/plugins/alerting/server/task_runner/alert_task_instance.ts @@ -9,14 +9,8 @@ import * as t from 'io-ts'; import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; -import { - SanitizedRule, - RuleTaskState, - ruleParamsSchema, - ruleStateSchema, - RuleTaskParams, - RuleTypeParams, -} from '../../common'; +import { ruleParamsSchema } from '@kbn/alerting-state-types'; +import { SanitizedRule, RuleTaskState, RuleTaskParams, RuleTypeParams } from '../../common'; export interface AlertTaskInstance extends ConcreteTaskInstance { state: RuleTaskState; @@ -42,15 +36,6 @@ export function taskInstanceToAlertTaskInstance( ); }, t.identity) ), - state: pipe( - ruleStateSchema.decode(taskInstance.state), - fold((e: t.Errors) => { - throw new Error( - `Task "${taskInstance.id}" ${ - alert ? `(underlying Alert "${alert.id}") ` : '' - }has invalid state at ${enumerateErrorFields(e)}` - ); - }, t.identity) - ), + state: taskInstance.state as RuleTaskState, }; } diff --git a/x-pack/plugins/alerting/server/task_runner/execution_handler.test.ts b/x-pack/plugins/alerting/server/task_runner/execution_handler.test.ts index 9f4b33dfd1723..ce86dd4756093 100644 --- a/x-pack/plugins/alerting/server/task_runner/execution_handler.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/execution_handler.test.ts @@ -13,10 +13,10 @@ import { renderActionParameterTemplatesDefault, } from '@kbn/actions-plugin/server/mocks'; import { KibanaRequest } from '@kbn/core/server'; +import { ActionsCompletion } from '@kbn/alerting-state-types'; import { InjectActionParamsOpts, injectActionParams } from './inject_action_params'; import { NormalizedRuleType } from '../rule_type_registry'; import { - ActionsCompletion, ThrottledActions, RuleTypeParams, RuleTypeState, @@ -166,7 +166,7 @@ const generateAlert = ({ meta: { maintenanceWindowIds, lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: lastScheduledActionsGroup, actions: throttledActions, }, @@ -188,7 +188,7 @@ const generateRecoveredAlert = ({ id, state }: { id: number; state?: AlertInstan state: state || { test: true }, meta: { lastScheduledActions: { - date: new Date(), + date: new Date().toISOString(), group: 'recovered', actions: {}, }, @@ -792,7 +792,7 @@ describe('Execution Handler', () => { await executionHandler.run( generateAlert({ id: 1, - throttledActions: { '111-111': { date: new Date(DATE_1970) } }, + throttledActions: { '111-111': { date: new Date(DATE_1970).toISOString() } }, }) ); @@ -1016,7 +1016,7 @@ describe('Execution Handler', () => { expect(result).toEqual({ throttledSummaryActions: { '111-111': { - date: new Date(), + date: new Date().toISOString(), }, }, }); 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 f4d8a3151ff2e..6214482ec2706 100644 --- a/x-pack/plugins/alerting/server/task_runner/execution_handler.ts +++ b/x-pack/plugins/alerting/server/task_runner/execution_handler.ts @@ -11,6 +11,7 @@ import { getRuleDetailsRoute, triggersActionsRoute } from '@kbn/rule-data-utils' import { asSavedObjectExecutionSource } from '@kbn/actions-plugin/server'; import { isEphemeralTaskRejectedDueToCapacityError } from '@kbn/task-manager-plugin/server'; import { ExecuteOptions as EnqueueExecutionOptions } from '@kbn/actions-plugin/server/create_execute_function'; +import { ActionsCompletion } from '@kbn/alerting-state-types'; import { ActionsClient } from '@kbn/actions-plugin/server/actions_client'; import { chunk } from 'lodash'; import { GetSummarizedAlertsParams, IAlertsClient } from '../alerts_client/types'; @@ -24,7 +25,6 @@ import { transformActionParams, transformSummaryActionParams } from './transform import { Alert } from '../alert'; import { NormalizedRuleType } from '../rule_type_registry'; import { - ActionsCompletion, AlertInstanceContext, AlertInstanceState, RuleAction, @@ -259,7 +259,7 @@ export class ExecutionHandler< }); if (isActionOnInterval(action)) { - throttledSummaryActions[action.uuid!] = { date: new Date() }; + throttledSummaryActions[action.uuid!] = { date: new Date().toISOString() }; } logActions.push({ diff --git a/x-pack/plugins/alerting/server/task_runner/fixtures.ts b/x-pack/plugins/alerting/server/task_runner/fixtures.ts index 9c7c528903c88..467d7460afc2b 100644 --- a/x-pack/plugins/alerting/server/task_runner/fixtures.ts +++ b/x-pack/plugins/alerting/server/task_runner/fixtures.ts @@ -383,7 +383,7 @@ export const generateRunnerResult = ({ ...(state && { alertInstances }), ...(state && { alertRecoveredInstances }), ...(state && { alertTypeState: {} }), - ...(state && { previousStartedAt: new Date('1970-01-01T00:00:00.000Z') }), + ...(state && { previousStartedAt: new Date('1970-01-01T00:00:00.000Z').toISOString() }), ...(state && { summaryActions }), }, hasError, @@ -440,7 +440,7 @@ export const generateAlertInstance = ( meta: { uuid: expect.any(String), lastScheduledActions: { - date: new Date(DATE_1970), + date: new Date(DATE_1970).toISOString(), group: 'default', ...(actions && { actions }), }, diff --git a/x-pack/plugins/alerting/server/task_runner/rule_action_helper.test.ts b/x-pack/plugins/alerting/server/task_runner/rule_action_helper.test.ts index 872672801b52c..c2ac1ab38a2fa 100644 --- a/x-pack/plugins/alerting/server/task_runner/rule_action_helper.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/rule_action_helper.test.ts @@ -146,21 +146,21 @@ describe('rule_action_helper', () => { const result = getSummaryActionsFromTaskState({ actions: [mockSummaryAction], summaryActions: { - '111-111': { date: new Date('01.01.2020') }, - '222-222': { date: new Date('01.01.2020') }, + '111-111': { date: new Date('01.01.2020').toISOString() }, + '222-222': { date: new Date('01.01.2020').toISOString() }, }, }); - expect(result).toEqual({ '111-111': { date: new Date('01.01.2020') } }); + expect(result).toEqual({ '111-111': { date: new Date('01.01.2020').toISOString() } }); }); test('should replace hash with uuid', () => { const result = getSummaryActionsFromTaskState({ actions: [mockSummaryAction], summaryActions: { - 'slack:summary:1d': { date: new Date('01.01.2020') }, + 'slack:summary:1d': { date: new Date('01.01.2020').toISOString() }, }, }); - expect(result).toEqual({ '111-111': { date: new Date('01.01.2020') } }); + expect(result).toEqual({ '111-111': { date: new Date('01.01.2020').toISOString() } }); }); }); @@ -180,7 +180,7 @@ describe('rule_action_helper', () => { jest.useRealTimers(); }); const logger = { debug: jest.fn() } as unknown as Logger; - const throttledSummaryActions = { '111-111': { date: new Date('2020-01-01T00:00:00.000Z') } }; + const throttledSummaryActions = { '111-111': { date: '2020-01-01T00:00:00.000Z' } }; test('should return false if the action does not have throttle filed', () => { const result = isSummaryActionThrottled({ @@ -227,7 +227,7 @@ describe('rule_action_helper', () => { test('should return false if the action is not in the task instance', () => { const result = isSummaryActionThrottled({ action: mockSummaryAction, - throttledSummaryActions: { '123-456': { date: new Date('2020-01-01T00:00:00.000Z') } }, + throttledSummaryActions: { '123-456': { date: '2020-01-01T00:00:00.000Z' } }, logger, }); expect(result).toBe(false); @@ -237,7 +237,7 @@ describe('rule_action_helper', () => { jest.advanceTimersByTime(3600000 * 2); const result = isSummaryActionThrottled({ action: mockSummaryAction, - throttledSummaryActions: { '123-456': { date: new Date('2020-01-01T00:00:00.000Z') } }, + throttledSummaryActions: { '123-456': { date: '2020-01-01T00:00:00.000Z' } }, logger, }); expect(result).toBe(false); diff --git a/x-pack/plugins/alerting/server/task_runner/rule_action_helper.ts b/x-pack/plugins/alerting/server/task_runner/rule_action_helper.ts index 79fe92b079026..a23323ffee2b7 100644 --- a/x-pack/plugins/alerting/server/task_runner/rule_action_helper.ts +++ b/x-pack/plugins/alerting/server/task_runner/rule_action_helper.ts @@ -58,7 +58,7 @@ export const isSummaryActionThrottled = ({ logger.debug(`Action'${action?.actionTypeId}:${action?.id}', has an invalid throttle interval`); } - const throttled = throttledAction.date.getTime() + throttleMills > Date.now(); + const throttled = new Date(throttledAction.date).getTime() + throttleMills > Date.now(); if (throttled) { logger.debug( 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 4e40531a49f2b..fcd2464058350 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 @@ -1565,7 +1565,7 @@ describe('Task Runner', () => { generateEnqueueFunctionInput({ isBulk, id: '1', foo: true }) ); expect(result.state.summaryActions).toEqual({ - '111-111': { date: new Date(DATE_1970) }, + '111-111': { date: new Date(DATE_1970).toISOString() }, }); } ); @@ -1835,9 +1835,7 @@ describe('Task Runner', () => { const runnerResult = await taskRunner.run(); - expect(runnerResult.state.previousStartedAt).toEqual( - new Date(originalAlertSate.previousStartedAt) - ); + expect(runnerResult.state.previousStartedAt).toEqual(originalAlertSate.previousStartedAt); expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); }); @@ -2745,7 +2743,7 @@ describe('Task Runner', () => { meta: { uuid: expect.any(String), lastScheduledActions: { - date: new Date(DATE_1970), + date: new Date(DATE_1970).toISOString(), group: 'default', }, flappingHistory: [true], @@ -2915,7 +2913,7 @@ describe('Task Runner', () => { meta: { uuid: expect.any(String), lastScheduledActions: { - date: new Date(DATE_1970), + date: new Date(DATE_1970).toISOString(), group: 'default', }, flappingHistory: [true], @@ -2932,7 +2930,7 @@ describe('Task Runner', () => { meta: { uuid: expect.any(String), lastScheduledActions: { - date: new Date(DATE_1970), + date: new Date(DATE_1970).toISOString(), group: 'default', }, flappingHistory: [true], 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 1f0598ce0f69c..6c871f63065a9 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -856,7 +856,7 @@ export class TaskRunner< ): RuleTaskState => { return { ...omit(runStateWithMetrics, ['metrics']), - previousStartedAt: startedAt, + previousStartedAt: startedAt?.toISOString(), }; }; diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts index 58f2520ce1f4a..3ed2a63feacdc 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts @@ -68,6 +68,7 @@ import { ruleRunMetricsStoreMock } from '../lib/rule_run_metrics_store.mock'; import { AlertsService } from '../alerts_service'; import { ReplaySubject } from 'rxjs'; import { IAlertsClient } from '../alerts_client/types'; +import { getDataStreamAdapter } from '../alerts_service/lib/data_stream_adapter'; jest.mock('uuid', () => ({ v4: () => '5f6aa57d-3e22-484e-bae8-cbed868f4d28', @@ -108,654 +109,683 @@ const ruleTypeWithAlerts: jest.Mocked = { }; describe('Task Runner', () => { - let mockedTaskInstance: ConcreteTaskInstance; - - beforeAll(() => { - fakeTimer = sinon.useFakeTimers(); - mockedTaskInstance = mockTaskInstance(); - }); - - afterAll(() => fakeTimer.restore()); - - const encryptedSavedObjectsClient = encryptedSavedObjectsMock.createClient(); - const services = alertsMock.createRuleExecutorServices(); - const actionsClient = actionsClientMock.create(); - const rulesClient = rulesClientMock.create(); - const ruleTypeRegistry = ruleTypeRegistryMock.create(); - const savedObjectsService = savedObjectsServiceMock.createInternalStartContract(); - const elasticsearchService = elasticsearchServiceMock.createInternalStart(); - const dataPlugin = dataPluginMock.createStartContract(); - const uiSettingsService = uiSettingsServiceMock.createStartContract(); - const inMemoryMetrics = inMemoryMetricsMock.create(); - const dataViewsMock = { - dataViewsServiceFactory: jest.fn().mockResolvedValue(dataViewPluginMocks.createStartContract()), - getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), - } as DataViewsServerPluginStart; - const mockAlertsService = alertsServiceMock.create(); - const mockAlertsClient = alertsClientMock.create(); - const mockLegacyAlertsClient = legacyAlertsClientMock.create(); - const ruleRunMetricsStore = ruleRunMetricsStoreMock.create(); - const maintenanceWindowClient = maintenanceWindowClientMock.create(); - - type TaskRunnerFactoryInitializerParamsType = jest.Mocked & { - actionsPlugin: jest.Mocked; - eventLogger: jest.Mocked; - executionContext: ReturnType; - }; - - const taskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType = { - data: dataPlugin, - dataViews: dataViewsMock, - savedObjects: savedObjectsService, - share: {} as SharePluginStart, - uiSettings: uiSettingsService, - elasticsearch: elasticsearchService, - actionsPlugin: actionsMock.createStart(), - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), - encryptedSavedObjectsClient, - logger, - executionContext: executionContextServiceMock.createInternalStartContract(), - spaceIdToNamespace: jest.fn().mockReturnValue(undefined), - basePathService: httpServiceMock.createBasePath(), - eventLogger: eventLoggerMock.create(), - internalSavedObjectsRepository: savedObjectsRepositoryMock.create(), - ruleTypeRegistry, - alertsService: mockAlertsService, - kibanaBaseUrl: 'https://localhost:5601', - supportsEphemeralTasks: false, - maxEphemeralActionsPerRule: 10, - maxAlerts: 1000, - cancelAlertsOnRuleTimeout: true, - usageCounter: mockUsageCounter, - actionsConfigMap: { - default: { - max: 10000, - }, - }, - getRulesSettingsClientWithRequest: jest.fn().mockReturnValue(rulesSettingsClientMock.create()), - getMaintenanceWindowClientWithRequest: jest.fn().mockReturnValue(maintenanceWindowClient), - }; - - beforeEach(() => { - jest.clearAllMocks(); - jest - .requireMock('../lib/wrap_scoped_cluster_client') - .createWrappedScopedClusterClientFactory.mockReturnValue({ - client: () => services.scopedClusterClient, - getMetrics: () => ({ - numSearches: 3, - esSearchDurationMs: 33, - totalSearchDurationMs: 23423, - }), - }); - savedObjectsService.getScopedClient.mockReturnValue(services.savedObjectsClient); - elasticsearchService.client.asScoped.mockReturnValue(services.scopedClusterClient); - maintenanceWindowClient.getActiveMaintenanceWindows.mockResolvedValue([]); - taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockReturnValue(rulesClient); - taskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mockResolvedValue( - actionsClient - ); - taskRunnerFactoryInitializerParams.actionsPlugin.renderActionParameterTemplates.mockImplementation( - (actionTypeId, actionId, params) => params - ); - ruleTypeRegistry.get.mockReturnValue(ruleTypeWithAlerts); - taskRunnerFactoryInitializerParams.executionContext.withContext.mockImplementation((ctx, fn) => - fn() - ); - taskRunnerFactoryInitializerParams.getRulesSettingsClientWithRequest.mockReturnValue( - rulesSettingsClientMock.create() - ); - taskRunnerFactoryInitializerParams.getMaintenanceWindowClientWithRequest.mockReturnValue( - maintenanceWindowClient - ); - mockedRuleTypeSavedObject.monitoring!.run.history = []; - mockedRuleTypeSavedObject.monitoring!.run.calculated_metrics.success_ratio = 0; - - alertingEventLogger.getStartAndDuration.mockImplementation(() => ({ start: new Date() })); - (AlertingEventLogger as jest.Mock).mockImplementation(() => alertingEventLogger); - logger.get.mockImplementation(() => logger); - ruleType.executor.mockResolvedValue({ state: {} }); - }); - - test('should not use legacy alerts client if alerts client created', async () => { - const spy1 = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - const spy2 = jest - .spyOn(RuleRunMetricsStoreModule, 'RuleRunMetricsStore') - .mockImplementation(() => ruleRunMetricsStore); - mockAlertsService.createAlertsClient.mockImplementation(() => mockAlertsClient); - mockAlertsClient.getAlertsToSerialize.mockResolvedValue({ - alertsToReturn: {}, - recoveredAlertsToReturn: {}, - }); - ruleRunMetricsStore.getMetrics.mockReturnValue({ - numSearches: 3, - totalSearchDurationMs: 23423, - esSearchDurationMs: 33, - numberOfTriggeredActions: 0, - numberOfGeneratedActions: 0, - numberOfActiveAlerts: 0, - numberOfRecoveredAlerts: 0, - numberOfNewAlerts: 0, - hasReachedAlertLimit: false, - triggeredActionsStatus: 'complete', - }); - const taskRunner = new TaskRunner({ - ruleType: ruleTypeWithAlerts, - taskInstance: { - ...mockedTaskInstance, - state: { - ...mockedTaskInstance.state, - previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(), - }, - }, - context: taskRunnerFactoryInitializerParams, - inMemoryMetrics, - }); - expect(AlertingEventLogger).toHaveBeenCalledTimes(1); + for (const useDataStreamForAlerts of [true, false]) { + const label = useDataStreamForAlerts ? 'data streams' : 'aliases'; - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); + let mockedTaskInstance: ConcreteTaskInstance; - await taskRunner.run(); + beforeAll(() => { + fakeTimer = sinon.useFakeTimers(); + mockedTaskInstance = mockTaskInstance(); + }); - expect(mockAlertsService.createAlertsClient).toHaveBeenCalledWith({ + afterAll(() => fakeTimer.restore()); + + const encryptedSavedObjectsClient = encryptedSavedObjectsMock.createClient(); + const services = alertsMock.createRuleExecutorServices(); + const actionsClient = actionsClientMock.create(); + const rulesClient = rulesClientMock.create(); + const ruleTypeRegistry = ruleTypeRegistryMock.create(); + const savedObjectsService = savedObjectsServiceMock.createInternalStartContract(); + const elasticsearchService = elasticsearchServiceMock.createInternalStart(); + const dataPlugin = dataPluginMock.createStartContract(); + const uiSettingsService = uiSettingsServiceMock.createStartContract(); + const inMemoryMetrics = inMemoryMetricsMock.create(); + const dataViewsMock = { + dataViewsServiceFactory: jest + .fn() + .mockResolvedValue(dataViewPluginMocks.createStartContract()), + getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), + } as DataViewsServerPluginStart; + const mockAlertsService = alertsServiceMock.create(); + const mockAlertsClient = alertsClientMock.create(); + const mockLegacyAlertsClient = legacyAlertsClientMock.create(); + const ruleRunMetricsStore = ruleRunMetricsStoreMock.create(); + const maintenanceWindowClient = maintenanceWindowClientMock.create(); + + type TaskRunnerFactoryInitializerParamsType = jest.Mocked & { + actionsPlugin: jest.Mocked; + eventLogger: jest.Mocked; + executionContext: ReturnType; + }; + + const taskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType = { + data: dataPlugin, + dataViews: dataViewsMock, + savedObjects: savedObjectsService, + share: {} as SharePluginStart, + uiSettings: uiSettingsService, + elasticsearch: elasticsearchService, + actionsPlugin: actionsMock.createStart(), + getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), + encryptedSavedObjectsClient, logger, - ruleType: ruleTypeWithAlerts, - namespace: 'default', - rule: { - consumer: 'bar', - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - id: '1', - name: 'rule-name', - parameters: { - bar: true, + executionContext: executionContextServiceMock.createInternalStartContract(), + spaceIdToNamespace: jest.fn().mockReturnValue(undefined), + basePathService: httpServiceMock.createBasePath(), + eventLogger: eventLoggerMock.create(), + internalSavedObjectsRepository: savedObjectsRepositoryMock.create(), + ruleTypeRegistry, + alertsService: mockAlertsService, + kibanaBaseUrl: 'https://localhost:5601', + supportsEphemeralTasks: false, + maxEphemeralActionsPerRule: 10, + maxAlerts: 1000, + cancelAlertsOnRuleTimeout: true, + usageCounter: mockUsageCounter, + actionsConfigMap: { + default: { + max: 10000, }, - revision: 0, - spaceId: 'default', - tags: ['rule-', '-tags'], }, - }); - expect(LegacyAlertsClientModule.LegacyAlertsClient).not.toHaveBeenCalled(); + getRulesSettingsClientWithRequest: jest + .fn() + .mockReturnValue(rulesSettingsClientMock.create()), + getMaintenanceWindowClientWithRequest: jest.fn().mockReturnValue(maintenanceWindowClient), + }; + + describe(`using ${label} for alert indices`, () => { + beforeEach(() => { + jest.clearAllMocks(); + jest + .requireMock('../lib/wrap_scoped_cluster_client') + .createWrappedScopedClusterClientFactory.mockReturnValue({ + client: () => services.scopedClusterClient, + getMetrics: () => ({ + numSearches: 3, + esSearchDurationMs: 33, + totalSearchDurationMs: 23423, + }), + }); + savedObjectsService.getScopedClient.mockReturnValue(services.savedObjectsClient); + elasticsearchService.client.asScoped.mockReturnValue(services.scopedClusterClient); + maintenanceWindowClient.getActiveMaintenanceWindows.mockResolvedValue([]); + taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockReturnValue(rulesClient); + taskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mockResolvedValue( + actionsClient + ); + taskRunnerFactoryInitializerParams.actionsPlugin.renderActionParameterTemplates.mockImplementation( + (actionTypeId, actionId, params) => params + ); + ruleTypeRegistry.get.mockReturnValue(ruleTypeWithAlerts); + taskRunnerFactoryInitializerParams.executionContext.withContext.mockImplementation( + (ctx, fn) => fn() + ); + taskRunnerFactoryInitializerParams.getRulesSettingsClientWithRequest.mockReturnValue( + rulesSettingsClientMock.create() + ); + taskRunnerFactoryInitializerParams.getMaintenanceWindowClientWithRequest.mockReturnValue( + maintenanceWindowClient + ); + mockedRuleTypeSavedObject.monitoring!.run.history = []; + mockedRuleTypeSavedObject.monitoring!.run.calculated_metrics.success_ratio = 0; + + alertingEventLogger.getStartAndDuration.mockImplementation(() => ({ start: new Date() })); + (AlertingEventLogger as jest.Mock).mockImplementation(() => alertingEventLogger); + logger.get.mockImplementation(() => logger); + ruleType.executor.mockResolvedValue({ state: {} }); + }); - testCorrectAlertsClientUsed({ - alertsClientToUse: mockAlertsClient, - alertsClientNotToUse: mockLegacyAlertsClient, - }); + test('should not use legacy alerts client if alerts client created', async () => { + const spy1 = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + const spy2 = jest + .spyOn(RuleRunMetricsStoreModule, 'RuleRunMetricsStore') + .mockImplementation(() => ruleRunMetricsStore); + mockAlertsService.createAlertsClient.mockImplementation(() => mockAlertsClient); + mockAlertsClient.getAlertsToSerialize.mockResolvedValue({ + alertsToReturn: {}, + recoveredAlertsToReturn: {}, + }); + ruleRunMetricsStore.getMetrics.mockReturnValue({ + numSearches: 3, + totalSearchDurationMs: 23423, + esSearchDurationMs: 33, + numberOfTriggeredActions: 0, + numberOfGeneratedActions: 0, + numberOfActiveAlerts: 0, + numberOfRecoveredAlerts: 0, + numberOfNewAlerts: 0, + hasReachedAlertLimit: false, + triggeredActionsStatus: 'complete', + }); + const taskRunner = new TaskRunner({ + ruleType: ruleTypeWithAlerts, + taskInstance: { + ...mockedTaskInstance, + state: { + ...mockedTaskInstance.state, + previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(), + }, + }, + context: taskRunnerFactoryInitializerParams, + inMemoryMetrics, + }); + expect(AlertingEventLogger).toHaveBeenCalledTimes(1); + + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); + + await taskRunner.run(); + + expect(mockAlertsService.createAlertsClient).toHaveBeenCalledWith({ + logger, + ruleType: ruleTypeWithAlerts, + namespace: 'default', + rule: { + consumer: 'bar', + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + id: '1', + name: 'rule-name', + parameters: { + bar: true, + }, + revision: 0, + spaceId: 'default', + tags: ['rule-', '-tags'], + }, + }); + expect(LegacyAlertsClientModule.LegacyAlertsClient).not.toHaveBeenCalled(); - expect(ruleType.executor).toHaveBeenCalledTimes(1); - expect(logger.debug).toHaveBeenCalledTimes(5); - expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); - expect(logger.debug).nthCalledWith( - 2, - 'deprecated ruleRunStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"ok"}' - ); - expect(logger.debug).nthCalledWith( - 3, - 'ruleRunStatus for test:1: {"outcome":"succeeded","outcomeOrder":0,"outcomeMsg":null,"warning":null,"alertsCount":{"active":0,"new":0,"recovered":0,"ignored":0}}' - ); - expect(logger.debug).nthCalledWith( - 4, - 'ruleRunMetrics for test:1: {"numSearches":3,"totalSearchDurationMs":23423,"esSearchDurationMs":33,"numberOfTriggeredActions":0,"numberOfGeneratedActions":0,"numberOfActiveAlerts":0,"numberOfRecoveredAlerts":0,"numberOfNewAlerts":0,"hasReachedAlertLimit":false,"triggeredActionsStatus":"complete"}' - ); - - expect( - taskRunnerFactoryInitializerParams.internalSavedObjectsRepository.update - ).toHaveBeenCalledWith(...generateSavedObjectParams({})); - - expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toBeCalledTimes(1); - expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toHaveBeenCalledWith( - { - id: '1', - name: 'execute test', - type: 'alert', - description: 'execute [test] with name [rule-name] in [default] namespace', - }, - expect.any(Function) - ); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - expect( - jest.requireMock('../lib/wrap_scoped_cluster_client').createWrappedScopedClusterClientFactory - ).toHaveBeenCalled(); - spy1.mockRestore(); - spy2.mockRestore(); - }); - - test('should successfully execute task with alerts client', async () => { - const alertsService = new AlertsService({ - logger, - pluginStop$: new ReplaySubject(1), - kibanaVersion: '8.8.0', - elasticsearchClientPromise: Promise.resolve(clusterClient), - }); - const spy = jest - .spyOn(alertsService, 'getContextInitializationPromise') - .mockResolvedValue({ result: true }); - - const taskRunner = new TaskRunner({ - ruleType: ruleTypeWithAlerts, - taskInstance: { - ...mockedTaskInstance, - state: { - ...mockedTaskInstance.state, - previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(), - }, - }, - context: { - ...taskRunnerFactoryInitializerParams, - alertsService, - }, - inMemoryMetrics, - }); - expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); - const runnerResult = await taskRunner.run(); - expect(runnerResult).toEqual(generateRunnerResult({ state: true, history: [true] })); - - expect(ruleType.executor).toHaveBeenCalledTimes(1); - const call = ruleType.executor.mock.calls[0][0]; - expect(call.params).toEqual({ bar: true }); - expect(call.startedAt).toStrictEqual(new Date(DATE_1970)); - expect(call.previousStartedAt).toStrictEqual(new Date(DATE_1970_5_MIN)); - expect(call.state).toEqual({}); - expect(call.rule).not.toBe(null); - expect(call.rule.id).toBe('1'); - expect(call.rule.name).toBe(RULE_NAME); - expect(call.rule.tags).toEqual(['rule-', '-tags']); - expect(call.rule.consumer).toBe('bar'); - expect(call.rule.enabled).toBe(true); - expect(call.rule.schedule).toEqual({ interval: '10s' }); - expect(call.rule.createdBy).toBe('rule-creator'); - expect(call.rule.updatedBy).toBe('rule-updater'); - expect(call.rule.createdAt).toBe(mockDate); - expect(call.rule.updatedAt).toBe(mockDate); - expect(call.rule.notifyWhen).toBe('onActiveAlert'); - expect(call.rule.throttle).toBe(null); - expect(call.rule.producer).toBe('alerts'); - expect(call.rule.ruleTypeId).toBe('test'); - expect(call.rule.ruleTypeName).toBe('My test rule'); - expect(call.rule.actions).toEqual(RULE_ACTIONS); - expect(call.services.alertFactory.create).toBeTruthy(); - expect(call.services.alertsClient).not.toBe(null); - expect(call.services.alertsClient?.report).toBeTruthy(); - expect(call.services.alertsClient?.setAlertData).toBeTruthy(); - expect(call.services.scopedClusterClient).toBeTruthy(); - expect(call.services).toBeTruthy(); - expect(logger.debug).toHaveBeenCalledTimes(6); - expect(logger.debug).nthCalledWith(1, `Initializing resources for AlertsService`); - expect(logger.debug).nthCalledWith(2, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); - expect(logger.debug).nthCalledWith( - 3, - 'deprecated ruleRunStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"ok"}' - ); - expect(logger.debug).nthCalledWith( - 4, - 'ruleRunStatus for test:1: {"outcome":"succeeded","outcomeOrder":0,"outcomeMsg":null,"warning":null,"alertsCount":{"active":0,"new":0,"recovered":0,"ignored":0}}' - ); - expect(logger.debug).nthCalledWith( - 5, - 'ruleRunMetrics for test:1: {"numSearches":3,"totalSearchDurationMs":23423,"esSearchDurationMs":33,"numberOfTriggeredActions":0,"numberOfGeneratedActions":0,"numberOfActiveAlerts":0,"numberOfRecoveredAlerts":0,"numberOfNewAlerts":0,"hasReachedAlertLimit":false,"triggeredActionsStatus":"complete"}' - ); - expect( - taskRunnerFactoryInitializerParams.internalSavedObjectsRepository.update - ).toHaveBeenCalledWith(...generateSavedObjectParams({})); - expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toBeCalledTimes(1); - expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toHaveBeenCalledWith( - { - id: '1', - name: 'execute test', - type: 'alert', - description: 'execute [test] with name [rule-name] in [default] namespace', - }, - expect.any(Function) - ); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - expect( - jest.requireMock('../lib/wrap_scoped_cluster_client').createWrappedScopedClusterClientFactory - ).toHaveBeenCalled(); - spy.mockRestore(); - }); - - test('should successfully execute task and index alert documents', async () => { - const alertsService = new AlertsService({ - logger, - pluginStop$: new ReplaySubject(1), - kibanaVersion: '8.8.0', - elasticsearchClientPromise: Promise.resolve(clusterClient), - }); - const spy = jest - .spyOn(alertsService, 'getContextInitializationPromise') - .mockResolvedValue({ result: true }); - - ruleTypeWithAlerts.executor.mockImplementation( - async ({ - services: executorServices, - }: RuleExecutorOptions< - RuleTypeParams, - RuleTypeState, - AlertInstanceState, - AlertInstanceContext, - string, - RuleAlertData - >) => { - executorServices.alertsClient?.report({ - id: '1', - actionGroup: 'default', - payload: { textField: 'foo', numericField: 27 }, + testCorrectAlertsClientUsed({ + alertsClientToUse: mockAlertsClient, + alertsClientNotToUse: mockLegacyAlertsClient, }); - return { state: {} }; - } - ); - - const taskRunner = new TaskRunner({ - ruleType: ruleTypeWithAlerts, - taskInstance: mockedTaskInstance, - context: { - ...taskRunnerFactoryInitializerParams, - alertsService, - }, - inMemoryMetrics, - }); - expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); - await taskRunner.run(); - - expect(ruleType.executor).toHaveBeenCalledTimes(1); - - expect(clusterClient.bulk).toHaveBeenCalledWith({ - index: '.alerts-test.alerts-default', - refresh: 'wait_for', - require_alias: true, - body: [ - { index: { _id: '5f6aa57d-3e22-484e-bae8-cbed868f4d28' } }, - // new alert doc - { - '@timestamp': DATE_1970, - event: { - action: 'open', - kind: 'signal', + + expect(ruleType.executor).toHaveBeenCalledTimes(1); + expect(logger.debug).toHaveBeenCalledTimes(5); + expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); + expect(logger.debug).nthCalledWith( + 2, + 'deprecated ruleRunStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"ok"}' + ); + expect(logger.debug).nthCalledWith( + 3, + 'ruleRunStatus for test:1: {"outcome":"succeeded","outcomeOrder":0,"outcomeMsg":null,"warning":null,"alertsCount":{"active":0,"new":0,"recovered":0,"ignored":0}}' + ); + expect(logger.debug).nthCalledWith( + 4, + 'ruleRunMetrics for test:1: {"numSearches":3,"totalSearchDurationMs":23423,"esSearchDurationMs":33,"numberOfTriggeredActions":0,"numberOfGeneratedActions":0,"numberOfActiveAlerts":0,"numberOfRecoveredAlerts":0,"numberOfNewAlerts":0,"hasReachedAlertLimit":false,"triggeredActionsStatus":"complete"}' + ); + + expect( + taskRunnerFactoryInitializerParams.internalSavedObjectsRepository.update + ).toHaveBeenCalledWith(...generateSavedObjectParams({})); + + expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toBeCalledTimes(1); + expect( + taskRunnerFactoryInitializerParams.executionContext.withContext + ).toHaveBeenCalledWith( + { + id: '1', + name: 'execute test', + type: 'alert', + description: 'execute [test] with name [rule-name] in [default] namespace', + }, + expect.any(Function) + ); + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + expect( + jest.requireMock('../lib/wrap_scoped_cluster_client') + .createWrappedScopedClusterClientFactory + ).toHaveBeenCalled(); + spy1.mockRestore(); + spy2.mockRestore(); + }); + + test('should successfully execute task with alerts client', async () => { + const alertsService = new AlertsService({ + logger, + pluginStop$: new ReplaySubject(1), + kibanaVersion: '8.8.0', + elasticsearchClientPromise: Promise.resolve(clusterClient), + dataStreamAdapter: getDataStreamAdapter({ useDataStreamForAlerts }), + }); + const spy = jest + .spyOn(alertsService, 'getContextInitializationPromise') + .mockResolvedValue({ result: true }); + + const taskRunner = new TaskRunner({ + ruleType: ruleTypeWithAlerts, + taskInstance: { + ...mockedTaskInstance, + state: { + ...mockedTaskInstance.state, + previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(), + }, + }, + context: { + ...taskRunnerFactoryInitializerParams, + alertsService, + }, + inMemoryMetrics, + }); + expect(AlertingEventLogger).toHaveBeenCalledTimes(1); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); + const runnerResult = await taskRunner.run(); + expect(runnerResult).toEqual(generateRunnerResult({ state: true, history: [true] })); + + expect(ruleType.executor).toHaveBeenCalledTimes(1); + const call = ruleType.executor.mock.calls[0][0]; + expect(call.params).toEqual({ bar: true }); + expect(call.startedAt).toStrictEqual(new Date(DATE_1970)); + expect(call.previousStartedAt).toStrictEqual(new Date(DATE_1970_5_MIN)); + expect(call.state).toEqual({}); + expect(call.rule).not.toBe(null); + expect(call.rule.id).toBe('1'); + expect(call.rule.name).toBe(RULE_NAME); + expect(call.rule.tags).toEqual(['rule-', '-tags']); + expect(call.rule.consumer).toBe('bar'); + expect(call.rule.enabled).toBe(true); + expect(call.rule.schedule).toEqual({ interval: '10s' }); + expect(call.rule.createdBy).toBe('rule-creator'); + expect(call.rule.updatedBy).toBe('rule-updater'); + expect(call.rule.createdAt).toBe(mockDate); + expect(call.rule.updatedAt).toBe(mockDate); + expect(call.rule.notifyWhen).toBe('onActiveAlert'); + expect(call.rule.throttle).toBe(null); + expect(call.rule.producer).toBe('alerts'); + expect(call.rule.ruleTypeId).toBe('test'); + expect(call.rule.ruleTypeName).toBe('My test rule'); + expect(call.rule.actions).toEqual(RULE_ACTIONS); + expect(call.services.alertFactory.create).toBeTruthy(); + expect(call.services.alertsClient).not.toBe(null); + expect(call.services.alertsClient?.report).toBeTruthy(); + expect(call.services.alertsClient?.setAlertData).toBeTruthy(); + expect(call.services.scopedClusterClient).toBeTruthy(); + expect(call.services).toBeTruthy(); + expect(logger.debug).toHaveBeenCalledTimes(6); + expect(logger.debug).nthCalledWith(1, `Initializing resources for AlertsService`); + expect(logger.debug).nthCalledWith(2, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); + expect(logger.debug).nthCalledWith( + 3, + 'deprecated ruleRunStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"ok"}' + ); + expect(logger.debug).nthCalledWith( + 4, + 'ruleRunStatus for test:1: {"outcome":"succeeded","outcomeOrder":0,"outcomeMsg":null,"warning":null,"alertsCount":{"active":0,"new":0,"recovered":0,"ignored":0}}' + ); + expect(logger.debug).nthCalledWith( + 5, + 'ruleRunMetrics for test:1: {"numSearches":3,"totalSearchDurationMs":23423,"esSearchDurationMs":33,"numberOfTriggeredActions":0,"numberOfGeneratedActions":0,"numberOfActiveAlerts":0,"numberOfRecoveredAlerts":0,"numberOfNewAlerts":0,"hasReachedAlertLimit":false,"triggeredActionsStatus":"complete"}' + ); + expect( + taskRunnerFactoryInitializerParams.internalSavedObjectsRepository.update + ).toHaveBeenCalledWith(...generateSavedObjectParams({})); + expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toBeCalledTimes(1); + expect( + taskRunnerFactoryInitializerParams.executionContext.withContext + ).toHaveBeenCalledWith( + { + id: '1', + name: 'execute test', + type: 'alert', + description: 'execute [test] with name [rule-name] in [default] namespace', + }, + expect.any(Function) + ); + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + expect( + jest.requireMock('../lib/wrap_scoped_cluster_client') + .createWrappedScopedClusterClientFactory + ).toHaveBeenCalled(); + spy.mockRestore(); + }); + + test('should successfully execute task and index alert documents', async () => { + const alertsService = new AlertsService({ + logger, + pluginStop$: new ReplaySubject(1), + kibanaVersion: '8.8.0', + elasticsearchClientPromise: Promise.resolve(clusterClient), + dataStreamAdapter: getDataStreamAdapter({ useDataStreamForAlerts }), + }); + const spy = jest + .spyOn(alertsService, 'getContextInitializationPromise') + .mockResolvedValue({ result: true }); + + ruleTypeWithAlerts.executor.mockImplementation( + async ({ + services: executorServices, + }: RuleExecutorOptions< + RuleTypeParams, + RuleTypeState, + AlertInstanceState, + AlertInstanceContext, + string, + RuleAlertData + >) => { + executorServices.alertsClient?.report({ + id: '1', + actionGroup: 'default', + payload: { textField: 'foo', numericField: 27 }, + }); + return { state: {} }; + } + ); + + const taskRunner = new TaskRunner({ + ruleType: ruleTypeWithAlerts, + taskInstance: mockedTaskInstance, + context: { + ...taskRunnerFactoryInitializerParams, + alertsService, }, - kibana: { - alert: { - action_group: 'default', - duration: { - us: '0', + inMemoryMetrics, + }); + expect(AlertingEventLogger).toHaveBeenCalledTimes(1); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); + await taskRunner.run(); + + expect(ruleType.executor).toHaveBeenCalledTimes(1); + + expect(clusterClient.bulk).toHaveBeenCalledWith({ + index: '.alerts-test.alerts-default', + refresh: 'wait_for', + require_alias: !useDataStreamForAlerts, + body: [ + { + create: { + _id: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + ...(useDataStreamForAlerts ? {} : { require_alias: true }), }, - flapping: false, - flapping_history: [true], - instance: { - id: '1', + }, + // new alert doc + { + '@timestamp': DATE_1970, + event: { + action: 'open', + kind: 'signal', }, - maintenance_window_ids: [], - rule: { - category: 'My test rule', - consumer: 'bar', - execution: { + kibana: { + alert: { + action_group: 'default', + duration: { + us: '0', + }, + flapping: false, + flapping_history: [true], + instance: { + id: '1', + }, + maintenance_window_ids: [], + rule: { + category: 'My test rule', + consumer: 'bar', + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, + name: 'rule-name', + parameters: { + bar: true, + }, + producer: 'alerts', + revision: 0, + rule_type_id: 'test', + tags: ['rule-', '-tags'], + uuid: '1', + }, + start: DATE_1970, + status: 'active', + time_range: { + gte: DATE_1970, + }, uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + workflow_status: 'open', }, - name: 'rule-name', - parameters: { - bar: true, - }, - producer: 'alerts', - revision: 0, - rule_type_id: 'test', - tags: ['rule-', '-tags'], - uuid: '1', - }, - start: DATE_1970, - status: 'active', - time_range: { - gte: DATE_1970, + space_ids: ['default'], + version: '8.8.0', }, - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - workflow_status: 'open', + numericField: 27, + textField: 'foo', + tags: ['rule-', '-tags'], + }, + ], + }); + spy.mockRestore(); + }); + + test('should default to legacy alerts client if error creating alerts client', async () => { + const spy1 = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + const spy2 = jest + .spyOn(RuleRunMetricsStoreModule, 'RuleRunMetricsStore') + .mockImplementation(() => ruleRunMetricsStore); + mockAlertsService.createAlertsClient.mockImplementation(() => { + throw new Error('Could not initialize!'); + }); + mockLegacyAlertsClient.getAlertsToSerialize.mockResolvedValue({ + alertsToReturn: {}, + recoveredAlertsToReturn: {}, + }); + ruleRunMetricsStore.getMetrics.mockReturnValue({ + numSearches: 3, + totalSearchDurationMs: 23423, + esSearchDurationMs: 33, + numberOfTriggeredActions: 0, + numberOfGeneratedActions: 0, + numberOfActiveAlerts: 0, + numberOfRecoveredAlerts: 0, + numberOfNewAlerts: 0, + hasReachedAlertLimit: false, + triggeredActionsStatus: 'complete', + }); + const taskRunner = new TaskRunner({ + ruleType: ruleTypeWithAlerts, + taskInstance: { + ...mockedTaskInstance, + state: { + ...mockedTaskInstance.state, + previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(), }, - space_ids: ['default'], - version: '8.8.0', }, - numericField: 27, - textField: 'foo', - tags: ['rule-', '-tags'], - }, - ], - }); - spy.mockRestore(); - }); - - test('should default to legacy alerts client if error creating alerts client', async () => { - const spy1 = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - const spy2 = jest - .spyOn(RuleRunMetricsStoreModule, 'RuleRunMetricsStore') - .mockImplementation(() => ruleRunMetricsStore); - mockAlertsService.createAlertsClient.mockImplementation(() => { - throw new Error('Could not initialize!'); - }); - mockLegacyAlertsClient.getAlertsToSerialize.mockResolvedValue({ - alertsToReturn: {}, - recoveredAlertsToReturn: {}, - }); - ruleRunMetricsStore.getMetrics.mockReturnValue({ - numSearches: 3, - totalSearchDurationMs: 23423, - esSearchDurationMs: 33, - numberOfTriggeredActions: 0, - numberOfGeneratedActions: 0, - numberOfActiveAlerts: 0, - numberOfRecoveredAlerts: 0, - numberOfNewAlerts: 0, - hasReachedAlertLimit: false, - triggeredActionsStatus: 'complete', - }); - const taskRunner = new TaskRunner({ - ruleType: ruleTypeWithAlerts, - taskInstance: { - ...mockedTaskInstance, - state: { - ...mockedTaskInstance.state, - previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(), - }, - }, - context: taskRunnerFactoryInitializerParams, - inMemoryMetrics, - }); - expect(AlertingEventLogger).toHaveBeenCalledTimes(1); + context: taskRunnerFactoryInitializerParams, + inMemoryMetrics, + }); + expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); - await taskRunner.run(); + await taskRunner.run(); - expect(mockAlertsService.createAlertsClient).toHaveBeenCalled(); - expect(logger.error).toHaveBeenCalledWith( - `Error initializing AlertsClient for context test. Using legacy alerts client instead. - Could not initialize!` - ); - expect(LegacyAlertsClientModule.LegacyAlertsClient).toHaveBeenCalledWith({ - logger, - ruleType: ruleTypeWithAlerts, - }); + expect(mockAlertsService.createAlertsClient).toHaveBeenCalled(); + expect(logger.error).toHaveBeenCalledWith( + `Error initializing AlertsClient for context test. Using legacy alerts client instead. - Could not initialize!` + ); + expect(LegacyAlertsClientModule.LegacyAlertsClient).toHaveBeenCalledWith({ + logger, + ruleType: ruleTypeWithAlerts, + }); - testCorrectAlertsClientUsed({ - alertsClientToUse: mockLegacyAlertsClient, - alertsClientNotToUse: mockAlertsClient, - }); + testCorrectAlertsClientUsed({ + alertsClientToUse: mockLegacyAlertsClient, + alertsClientNotToUse: mockAlertsClient, + }); - expect(ruleType.executor).toHaveBeenCalledTimes(1); + expect(ruleType.executor).toHaveBeenCalledTimes(1); - expect(logger.debug).toHaveBeenCalledTimes(5); - expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); + expect(logger.debug).toHaveBeenCalledTimes(5); + expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); - expect( - taskRunnerFactoryInitializerParams.internalSavedObjectsRepository.update - ).toHaveBeenCalledWith(...generateSavedObjectParams({})); + expect( + taskRunnerFactoryInitializerParams.internalSavedObjectsRepository.update + ).toHaveBeenCalledWith(...generateSavedObjectParams({})); - expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toBeCalledTimes(1); - expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toHaveBeenCalledWith( - { - id: '1', - name: 'execute test', - type: 'alert', - description: 'execute [test] with name [rule-name] in [default] namespace', - }, - expect.any(Function) - ); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - expect( - jest.requireMock('../lib/wrap_scoped_cluster_client').createWrappedScopedClusterClientFactory - ).toHaveBeenCalled(); - spy1.mockRestore(); - spy2.mockRestore(); - }); - - test('should default to legacy alerts client if alert service is not defined', async () => { - const spy1 = jest - .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') - .mockImplementation(() => mockLegacyAlertsClient); - const spy2 = jest - .spyOn(RuleRunMetricsStoreModule, 'RuleRunMetricsStore') - .mockImplementation(() => ruleRunMetricsStore); - mockLegacyAlertsClient.getAlertsToSerialize.mockResolvedValue({ - alertsToReturn: {}, - recoveredAlertsToReturn: {}, - }); - ruleRunMetricsStore.getMetrics.mockReturnValue({ - numSearches: 3, - totalSearchDurationMs: 23423, - esSearchDurationMs: 33, - numberOfTriggeredActions: 0, - numberOfGeneratedActions: 0, - numberOfActiveAlerts: 0, - numberOfRecoveredAlerts: 0, - numberOfNewAlerts: 0, - hasReachedAlertLimit: false, - triggeredActionsStatus: 'complete', - }); - const taskRunner = new TaskRunner({ - ruleType: ruleTypeWithAlerts, - taskInstance: { - ...mockedTaskInstance, - state: { - ...mockedTaskInstance.state, - previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(), - }, - }, - context: { ...taskRunnerFactoryInitializerParams, alertsService: null }, - inMemoryMetrics, - }); - expect(AlertingEventLogger).toHaveBeenCalledTimes(1); + expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toBeCalledTimes(1); + expect( + taskRunnerFactoryInitializerParams.executionContext.withContext + ).toHaveBeenCalledWith( + { + id: '1', + name: 'execute test', + type: 'alert', + description: 'execute [test] with name [rule-name] in [default] namespace', + }, + expect.any(Function) + ); + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + expect( + jest.requireMock('../lib/wrap_scoped_cluster_client') + .createWrappedScopedClusterClientFactory + ).toHaveBeenCalled(); + spy1.mockRestore(); + spy2.mockRestore(); + }); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); + test('should default to legacy alerts client if alert service is not defined', async () => { + const spy1 = jest + .spyOn(LegacyAlertsClientModule, 'LegacyAlertsClient') + .mockImplementation(() => mockLegacyAlertsClient); + const spy2 = jest + .spyOn(RuleRunMetricsStoreModule, 'RuleRunMetricsStore') + .mockImplementation(() => ruleRunMetricsStore); + mockLegacyAlertsClient.getAlertsToSerialize.mockResolvedValue({ + alertsToReturn: {}, + recoveredAlertsToReturn: {}, + }); + ruleRunMetricsStore.getMetrics.mockReturnValue({ + numSearches: 3, + totalSearchDurationMs: 23423, + esSearchDurationMs: 33, + numberOfTriggeredActions: 0, + numberOfGeneratedActions: 0, + numberOfActiveAlerts: 0, + numberOfRecoveredAlerts: 0, + numberOfNewAlerts: 0, + hasReachedAlertLimit: false, + triggeredActionsStatus: 'complete', + }); + const taskRunner = new TaskRunner({ + ruleType: ruleTypeWithAlerts, + taskInstance: { + ...mockedTaskInstance, + state: { + ...mockedTaskInstance.state, + previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(), + }, + }, + context: { ...taskRunnerFactoryInitializerParams, alertsService: null }, + inMemoryMetrics, + }); + expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - await taskRunner.run(); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); - expect(mockAlertsService.createAlertsClient).not.toHaveBeenCalled(); - expect(logger.error).not.toHaveBeenCalled(); - expect(LegacyAlertsClientModule.LegacyAlertsClient).toHaveBeenCalledWith({ - logger, - ruleType: ruleTypeWithAlerts, - }); + await taskRunner.run(); - testCorrectAlertsClientUsed({ - alertsClientToUse: mockLegacyAlertsClient, - alertsClientNotToUse: mockAlertsClient, - }); + expect(mockAlertsService.createAlertsClient).not.toHaveBeenCalled(); + expect(logger.error).not.toHaveBeenCalled(); + expect(LegacyAlertsClientModule.LegacyAlertsClient).toHaveBeenCalledWith({ + logger, + ruleType: ruleTypeWithAlerts, + }); - expect(ruleType.executor).toHaveBeenCalledTimes(1); + testCorrectAlertsClientUsed({ + alertsClientToUse: mockLegacyAlertsClient, + alertsClientNotToUse: mockAlertsClient, + }); - expect(logger.debug).toHaveBeenCalledTimes(5); - expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); + expect(ruleType.executor).toHaveBeenCalledTimes(1); - expect( - taskRunnerFactoryInitializerParams.internalSavedObjectsRepository.update - ).toHaveBeenCalledWith(...generateSavedObjectParams({})); + expect(logger.debug).toHaveBeenCalledTimes(5); + expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); - expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toBeCalledTimes(1); - expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toHaveBeenCalledWith( - { - id: '1', - name: 'execute test', - type: 'alert', - description: 'execute [test] with name [rule-name] in [default] namespace', - }, - expect.any(Function) - ); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - expect( - jest.requireMock('../lib/wrap_scoped_cluster_client').createWrappedScopedClusterClientFactory - ).toHaveBeenCalled(); - spy1.mockRestore(); - spy2.mockRestore(); - }); - - function testCorrectAlertsClientUsed< - AlertData extends RuleAlertData = never, - State extends AlertInstanceState = never, - Context extends AlertInstanceContext = never, - ActionGroupIds extends string = 'default', - RecoveryActionGroupId extends string = 'recovered' - >({ - alertsClientToUse, - alertsClientNotToUse, - }: { - alertsClientToUse: IAlertsClient< - AlertData, - State, - Context, - ActionGroupIds, - RecoveryActionGroupId - >; - alertsClientNotToUse: IAlertsClient< - AlertData, - State, - Context, - ActionGroupIds, - RecoveryActionGroupId - >; - }) { - expect(alertsClientToUse.initializeExecution).toHaveBeenCalledWith({ - activeAlertsFromState: {}, - flappingSettings: { - enabled: true, - lookBackWindow: 20, - statusChangeThreshold: 4, - }, - maxAlerts: 1000, - recoveredAlertsFromState: {}, - ruleLabel: "test:1: 'rule-name'", - }); - expect(alertsClientNotToUse.initializeExecution).not.toHaveBeenCalled(); - - expect(alertsClientToUse.checkLimitUsage).toHaveBeenCalled(); - expect(alertsClientNotToUse.checkLimitUsage).not.toHaveBeenCalled(); - - expect(alertsClientToUse.processAndLogAlerts).toHaveBeenCalledWith({ - eventLogger: alertingEventLogger, - ruleRunMetricsStore, - shouldLogAlerts: true, - flappingSettings: { - enabled: true, - lookBackWindow: 20, - statusChangeThreshold: 4, - }, - notifyWhen: RuleNotifyWhen.ACTIVE, - maintenanceWindowIds: [], + expect( + taskRunnerFactoryInitializerParams.internalSavedObjectsRepository.update + ).toHaveBeenCalledWith(...generateSavedObjectParams({})); + + expect(taskRunnerFactoryInitializerParams.executionContext.withContext).toBeCalledTimes(1); + expect( + taskRunnerFactoryInitializerParams.executionContext.withContext + ).toHaveBeenCalledWith( + { + id: '1', + name: 'execute test', + type: 'alert', + description: 'execute [test] with name [rule-name] in [default] namespace', + }, + expect.any(Function) + ); + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + expect( + jest.requireMock('../lib/wrap_scoped_cluster_client') + .createWrappedScopedClusterClientFactory + ).toHaveBeenCalled(); + spy1.mockRestore(); + spy2.mockRestore(); + }); }); - expect(alertsClientNotToUse.processAndLogAlerts).not.toHaveBeenCalled(); - expect(alertsClientToUse.persistAlerts).toHaveBeenCalled(); - expect(alertsClientNotToUse.persistAlerts).not.toHaveBeenCalled(); + function testCorrectAlertsClientUsed< + AlertData extends RuleAlertData = never, + State extends AlertInstanceState = never, + Context extends AlertInstanceContext = never, + ActionGroupIds extends string = 'default', + RecoveryActionGroupId extends string = 'recovered' + >({ + alertsClientToUse, + alertsClientNotToUse, + }: { + alertsClientToUse: IAlertsClient< + AlertData, + State, + Context, + ActionGroupIds, + RecoveryActionGroupId + >; + alertsClientNotToUse: IAlertsClient< + AlertData, + State, + Context, + ActionGroupIds, + RecoveryActionGroupId + >; + }) { + expect(alertsClientToUse.initializeExecution).toHaveBeenCalledWith({ + activeAlertsFromState: {}, + flappingSettings: { + enabled: true, + lookBackWindow: 20, + statusChangeThreshold: 4, + }, + maxAlerts: 1000, + recoveredAlertsFromState: {}, + ruleLabel: "test:1: 'rule-name'", + }); + expect(alertsClientNotToUse.initializeExecution).not.toHaveBeenCalled(); + + expect(alertsClientToUse.checkLimitUsage).toHaveBeenCalled(); + expect(alertsClientNotToUse.checkLimitUsage).not.toHaveBeenCalled(); + + expect(alertsClientToUse.processAndLogAlerts).toHaveBeenCalledWith({ + eventLogger: alertingEventLogger, + ruleRunMetricsStore, + shouldLogAlerts: true, + flappingSettings: { + enabled: true, + lookBackWindow: 20, + statusChangeThreshold: 4, + }, + notifyWhen: RuleNotifyWhen.ACTIVE, + maintenanceWindowIds: [], + }); + expect(alertsClientNotToUse.processAndLogAlerts).not.toHaveBeenCalled(); + + expect(alertsClientToUse.persistAlerts).toHaveBeenCalled(); + expect(alertsClientNotToUse.persistAlerts).not.toHaveBeenCalled(); - expect(alertsClientToUse.getProcessedAlerts).toHaveBeenCalledWith('activeCurrent'); - expect(alertsClientToUse.getProcessedAlerts).toHaveBeenCalledWith('recoveredCurrent'); - expect(alertsClientNotToUse.getProcessedAlerts).not.toHaveBeenCalled(); + expect(alertsClientToUse.getProcessedAlerts).toHaveBeenCalledWith('activeCurrent'); + expect(alertsClientToUse.getProcessedAlerts).toHaveBeenCalledWith('recoveredCurrent'); + expect(alertsClientNotToUse.getProcessedAlerts).not.toHaveBeenCalled(); - expect(alertsClientToUse.getAlertsToSerialize).toHaveBeenCalled(); - expect(alertsClientNotToUse.getAlertsToSerialize).not.toHaveBeenCalled(); + expect(alertsClientToUse.getAlertsToSerialize).toHaveBeenCalled(); + expect(alertsClientNotToUse.getAlertsToSerialize).not.toHaveBeenCalled(); + } } }); diff --git a/x-pack/plugins/alerting/server/test_utils/index.ts b/x-pack/plugins/alerting/server/test_utils/index.ts index 589dae529cee6..ec82b884fb427 100644 --- a/x-pack/plugins/alerting/server/test_utils/index.ts +++ b/x-pack/plugins/alerting/server/test_utils/index.ts @@ -6,6 +6,7 @@ */ import { RawAlertInstance } from '../../common'; +import { AlertingConfig } from '../config'; interface Resolvable { resolve: (arg: T) => void; @@ -45,3 +46,29 @@ export function alertsWithAnyUUID( } return newAlerts; } + +export function generateAlertingConfig(): AlertingConfig { + return { + healthCheck: { + interval: '5m', + }, + enableFrameworkAlerts: false, + invalidateApiKeysTask: { + interval: '5m', + removalDelay: '1h', + }, + maxEphemeralActionsPerAlert: 10, + cancelAlertsOnRuleTimeout: true, + rules: { + minimumScheduleInterval: { value: '1m', enforce: false }, + run: { + actions: { + max: 1000, + }, + alerts: { + max: 1000, + }, + }, + }, + }; +} diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index c7e8294759657..bee42c98dc075 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -468,3 +468,5 @@ export interface RawRule extends SavedObjectAttributes { revision: number; running?: boolean | null; } + +export type { DataStreamAdapter } from './alerts_service/lib/data_stream_adapter'; diff --git a/x-pack/plugins/alerting/tsconfig.json b/x-pack/plugins/alerting/tsconfig.json index 9a3976445c235..f38fbd085c7f0 100644 --- a/x-pack/plugins/alerting/tsconfig.json +++ b/x-pack/plugins/alerting/tsconfig.json @@ -56,6 +56,7 @@ "@kbn/core-capabilities-common", "@kbn/unified-search-plugin", "@kbn/core-http-server-mocks", + "@kbn/serverless", "@kbn/core-http-router-server-mocks", ], "exclude": ["target/**/*"] diff --git a/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap b/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap index 7e0d699fddfc0..2bed81c9c05c3 100644 --- a/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap +++ b/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap @@ -14,76 +14,148 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "services_per_agent": { "properties": { "android/java": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the android/java agent within the last day" + } }, "dotnet": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the dotnet (.Net) agent within the last day" + } }, "iOS/swift": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the iOS/swift agent within the last day" + } }, "go": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the go agent within the last day" + } }, "java": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the Java agent within the last day" + } }, "js-base": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the js-base agent within the last day" + } }, "nodejs": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the nodeJS agent within the last day" + } }, "php": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the PHH agent within the last day" + } }, "python": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the Python agent within the last day" + } }, "ruby": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the Ruby agent within the last day" + } }, "rum-js": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the rum-js agent within the last day" + } }, "otlp": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp agent within the last day" + } }, "opentelemetry/cpp": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/cpp agent within the last day" + } }, "opentelemetry/dotnet": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/dotnet agent within the last day" + } }, "opentelemetry/erlang": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/erlang agent within the last day" + } }, "opentelemetry/go": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/go agent within the last day" + } }, "opentelemetry/java": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/java agent within the last day" + } }, "opentelemetry/nodejs": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/nodejs agent within the last day" + } }, "opentelemetry/php": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/php agent within the last day" + } }, "opentelemetry/python": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/python agent within the last day" + } }, "opentelemetry/ruby": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/ruby agent within the last day" + } }, "opentelemetry/rust": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/rust agent within the last day" + } }, "opentelemetry/swift": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/swift agent within the last day" + } }, "opentelemetry/webjs": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry/webjs agent within the last day" + } } } }, @@ -1140,60 +1212,96 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "current_implementation": { "properties": { "expected_metric_document_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } }, "transaction_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } } } }, "no_observer_name": { "properties": { "expected_metric_document_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } }, "transaction_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } } } }, "no_rum": { "properties": { "expected_metric_document_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } }, "transaction_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } } } }, "no_rum_no_observer_name": { "properties": { "expected_metric_document_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } }, "transaction_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } } } }, "only_rum": { "properties": { "expected_metric_document_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } }, "transaction_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } } } }, "only_rum_no_observer_name": { "properties": { "expected_metric_document_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } }, "transaction_count": { - "type": "long" + "type": "long", + "_meta": { + "description": "" + } } } } @@ -1366,10 +1474,10 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "services": { "properties": { "1d": { - "type": "long" - }, - "all": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of unique services within the last day" + } } } }, @@ -1552,7 +1660,10 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "shards": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of shards for metric indices" + } } } }, @@ -1563,14 +1674,20 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "docs": { "properties": { "count": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of metric documents overall" + } } } }, "store": { "properties": { "size_in_bytes": { - "type": "long" + "type": "long", + "_meta": { + "description": "Size of the metric indicess in byte units overall." + } } } } @@ -1587,7 +1704,7 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "total": { "type": "long", "_meta": { - "description": "Total number of shards overall" + "description": "Total number of shards for span and trasnaction indices" } } } @@ -1819,7 +1936,10 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "pod": { "properties": { "name": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Kuberneted pod name " + } } } } @@ -1828,7 +1948,10 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "container": { "properties": { "id": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Container id" + } } } } diff --git a/x-pack/plugins/apm/common/rules/schema.ts b/x-pack/plugins/apm/common/rules/schema.ts index 02fb3a458015a..9041e4c0c8e5a 100644 --- a/x-pack/plugins/apm/common/rules/schema.ts +++ b/x-pack/plugins/apm/common/rules/schema.ts @@ -9,6 +9,16 @@ import { schema, TypeOf } from '@kbn/config-schema'; import { ML_ANOMALY_SEVERITY } from '@kbn/ml-anomaly-utils/anomaly_severity'; import { AggregationType, ApmRuleType } from './apm_rule_types'; +export const searchConfigurationSchema = schema.object({ + query: schema.object({ + query: schema.oneOf([ + schema.string(), + schema.recordOf(schema.string(), schema.any()), + ]), + language: schema.string(), + }), +}); + export const errorCountParamsSchema = schema.object({ windowSize: schema.number(), windowUnit: schema.string(), @@ -18,7 +28,7 @@ export const errorCountParamsSchema = schema.object({ groupBy: schema.maybe(schema.arrayOf(schema.string())), errorGroupingKey: schema.maybe(schema.string()), useKqlFilter: schema.maybe(schema.boolean()), - kqlFilter: schema.maybe(schema.string()), + searchConfiguration: schema.maybe(searchConfigurationSchema), }); export const transactionDurationParamsSchema = schema.object({ @@ -36,7 +46,7 @@ export const transactionDurationParamsSchema = schema.object({ environment: schema.string(), groupBy: schema.maybe(schema.arrayOf(schema.string())), useKqlFilter: schema.maybe(schema.boolean()), - kqlFilter: schema.maybe(schema.string()), + searchConfiguration: schema.maybe(searchConfigurationSchema), }); export const anomalyParamsSchema = schema.object({ @@ -63,7 +73,7 @@ export const transactionErrorRateParamsSchema = schema.object({ environment: schema.string(), groupBy: schema.maybe(schema.arrayOf(schema.string())), useKqlFilter: schema.maybe(schema.boolean()), - kqlFilter: schema.maybe(schema.string()), + searchConfiguration: schema.maybe(searchConfigurationSchema), }); type ErrorCountParamsType = TypeOf; @@ -75,6 +85,8 @@ type TransactionErrorRateParamsType = TypeOf< typeof transactionErrorRateParamsSchema >; +export type SearchConfigurationType = TypeOf; + export interface ApmRuleParamsType { [ApmRuleType.TransactionDuration]: TransactionDurationParamsType; [ApmRuleType.ErrorCount]: ErrorCountParamsType; diff --git a/x-pack/plugins/apm/common/utils/formatters/duration.ts b/x-pack/plugins/apm/common/utils/formatters/duration.ts index bf83ed2e093ea..49040f64bb51d 100644 --- a/x-pack/plugins/apm/common/utils/formatters/duration.ts +++ b/x-pack/plugins/apm/common/utils/formatters/duration.ts @@ -31,7 +31,11 @@ export type TimeFormatter = ( options?: FormatterOptions ) => ConvertedDuration; -type TimeFormatterBuilder = (max: number, threshold?: number) => TimeFormatter; +type TimeFormatterBuilder = ( + max: number, + threshold?: number, + scalingFactor?: number +) => TimeFormatter; // threshold defines the value from which upwards there should be no decimal places. function getUnitLabelAndConvertedValue( @@ -150,10 +154,15 @@ function getDurationUnitKey(max: number, threshold = 10): DurationTimeUnit { // memoizer with a custom resolver to consider both arguments max/threshold. // by default lodash's memoize only considers the first argument. export const getDurationFormatter: TimeFormatterBuilder = memoize( - (max: number, threshold: number = 10) => { + (max: number, threshold: number = 10, scalingFactor: number = 1) => { const unit = getDurationUnitKey(max, threshold); return (value: Maybe, { defaultValue }: FormatterOptions = {}) => { - return convertTo({ unit, microseconds: value, defaultValue, threshold }); + return convertTo({ + unit, + microseconds: isFiniteNumber(value) ? value * scalingFactor : value, + defaultValue, + threshold, + }); }; }, (max, threshold) => `${max}_${threshold}` diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/service_overview/instances_table.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/service_overview/instances_table.cy.ts index 8e1dda2b69e5f..c734188b5495d 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/service_overview/instances_table.cy.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/service_overview/instances_table.cy.ts @@ -108,7 +108,6 @@ describe('Instances table', () => { cy.wait('@instancesDetailsRequest'); cy.getByTestSubj(`instanceDetailsButton_${serviceNodeName}`).realClick(); - cy.getByTestSubj('loadingSpinner').should('be.visible'); cy.wait('@instanceDetailsRequest').then(() => { cy.contains('Service'); }); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/service_overview/time_comparison.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/service_overview/time_comparison.cy.ts index c3824036283cf..be31d27e46736 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/service_overview/time_comparison.cy.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/service_overview/time_comparison.cy.ts @@ -50,7 +50,7 @@ const apisToIntercept = [ }, ]; -describe.skip('Service overview: Time Comparison', () => { +describe('Service overview: Time Comparison', () => { before(() => { synthtrace.index( opbeans({ @@ -108,48 +108,53 @@ describe.skip('Service overview: Time Comparison', () => { cy.getByTestSubj('comparisonSelect').should('have.value', '1w'); }); - it('changes comparison type when a new time range is selected', () => { - cy.visitKibana(serviceOverviewHref); - cy.contains('opbeans-java'); - // Time comparison default value - cy.getByTestSubj('comparisonSelect').should('have.value', '1d'); - cy.contains('Day before'); - cy.contains('Week before'); - - cy.selectAbsoluteTimeRange( - '2021-10-10T00:00:00.000Z', - '2021-10-20T00:00:00.000Z' - ); - - cy.getByTestSubj('querySubmitButton').click(); - - cy.getByTestSubj('comparisonSelect').should('have.value', '864000000ms'); - cy.getByTestSubj('comparisonSelect').should( - 'not.contain.text', - 'Day before' - ); - cy.getByTestSubj('comparisonSelect').should( - 'not.contain.text', - 'Week before' - ); - - cy.changeTimeRange('Today'); - cy.contains('Day before'); - cy.contains('Week before'); + describe('changes comparison type when a new time range is selected', () => { + it('when selecting a manual time range, comparison should display the custom time range', () => { + cy.visitKibana(serviceOverviewHref); + cy.contains('opbeans-java'); + // Time comparison default value + cy.getByTestSubj('comparisonSelect').should('have.value', '1d'); + cy.contains('Day before'); + cy.contains('Week before'); + + cy.selectAbsoluteTimeRange( + '2021-10-10T00:00:00.000Z', + '2021-10-20T00:00:00.000Z' + ); - cy.changeTimeRange('Last 24 hours'); - cy.getByTestSubj('comparisonSelect').should('have.value', '1d'); - cy.contains('Day before'); - cy.contains('Week before'); + cy.getByTestSubj('querySubmitButton').click(); - cy.changeTimeRange('Last 7 days'); - cy.getByTestSubj('comparisonSelect').should('have.value', '1w'); - cy.getByTestSubj('comparisonSelect').should('contain.text', 'Week before'); - cy.getByTestSubj('comparisonSelect').should( - 'not.contain.text', - 'Day before' - ); - cy.contains('Week before'); + cy.getByTestSubj('comparisonSelect').should('have.value', '864000000ms'); + cy.getByTestSubj('comparisonSelect').should( + 'not.contain.text', + 'Day before' + ); + cy.getByTestSubj('comparisonSelect').should( + 'not.contain.text', + 'Week before' + ); + }); + it('when selecting Today from time range, comparison should display both day and week options', () => { + cy.visitKibana(serviceOverviewHref); + cy.changeTimeRange('Today'); + cy.getByTestSubj('comparisonSelect').should('have.value', '1d'); + cy.contains('Day before'); + cy.contains('Week before'); + }); + // Skipped as the test is Flaky + xit('when selecting Last Week from time range, comparison should only display week options', () => { + cy.visitKibana(serviceOverviewHref); + cy.changeTimeRange('Last 7 days'); + cy.getByTestSubj('comparisonSelect').should('have.value', '1w'); + cy.getByTestSubj('comparisonSelect').should( + 'contain.text', + 'Week before' + ); + cy.getByTestSubj('comparisonSelect').should( + 'not.contain.text', + 'Day before' + ); + }); }); it('hovers over throughput chart shows previous and current period', () => { diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/storage_explorer/storage_explorer.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/storage_explorer/storage_explorer.cy.ts index 5abd41ba5fe0c..bfa0aaa79d987 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/storage_explorer/storage_explorer.cy.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/storage_explorer/storage_explorer.cy.ts @@ -187,7 +187,6 @@ describe('Storage Explorer', () => { cy.contains('opbeans-node'); cy.getByTestSubj('storageDetailsButton_opbeans-node').click(); - cy.getByTestSubj('loadingSpinner').should('be.visible'); cy.wait('@storageDetailsRequest'); cy.contains('Service storage details'); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts index e520dc5f92579..c191a9add4e96 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts @@ -80,19 +80,25 @@ Cypress.Commands.add('visitKibana', (url: string) => { }); }); +// This command expects from and to both values to be present on the URL where +// this command is being executed. If from and to values are not present, +// the date picker renders singleValueInput where this command won't work. Cypress.Commands.add( 'selectAbsoluteTimeRange', (start: string, end: string) => { const format = 'MMM D, YYYY @ HH:mm:ss.SSS'; cy.getByTestSubj('superDatePickerstartDatePopoverButton').click(); - cy.getByTestSubj('superDatePickerAbsoluteDateInput') - .eq(0) + cy.contains('Start date') + .nextAll() + .find('[data-test-subj="superDatePickerAbsoluteDateInput"]') .clear({ force: true }) .type(moment(start).format(format), { force: true }); + cy.getByTestSubj('superDatePickerendDatePopoverButton').click(); - cy.getByTestSubj('superDatePickerAbsoluteDateInput') - .eq(1) + cy.contains('End date') + .nextAll() + .find('[data-test-subj="superDatePickerAbsoluteDateInput"]') .clear({ force: true }) .type(moment(end).format(format), { force: true }); } diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts b/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts index fbbd35524d43d..189633ec95975 100644 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts +++ b/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts @@ -8,6 +8,7 @@ import { i18n } from '@kbn/i18n'; import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; import { callApmApi } from '../services/rest/create_call_apm_api'; +import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; export function registerGetApmServiceSummaryFunction({ registerFunction, @@ -35,20 +36,20 @@ alerts and anomalies.`, type: 'object', properties: { 'service.name': { - type: 'string', + ...NON_EMPTY_STRING, description: 'The name of the service that should be summarized.', }, 'service.environment': { - type: 'string', + ...NON_EMPTY_STRING, description: 'The environment that the service is running in', }, start: { - type: 'string', + ...NON_EMPTY_STRING, description: 'The start of the time range, in Elasticsearch date math, like `now`.', }, end: { - type: 'string', + ...NON_EMPTY_STRING, description: 'The end of the time range, in Elasticsearch date math, like `now-24h`.', }, diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.ts b/x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.ts new file mode 100644 index 0000000000000..83f1c53d5ca70 --- /dev/null +++ b/x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; +import { ServiceHealthStatus } from '../../common/service_health_status'; +import { callApmApi } from '../services/rest/create_call_apm_api'; +import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; + +export function registerGetApmServicesListFunction({ + registerFunction, +}: { + registerFunction: RegisterFunctionDefinition; +}) { + registerFunction( + { + name: 'get_apm_services_list', + contexts: ['apm'], + description: `Gets a list of services`, + descriptionForUser: i18n.translate( + 'xpack.apm.observabilityAiAssistant.functions.registerGetApmServicesList.descriptionForUser', + { + defaultMessage: `Gets the list of monitored services, their health status, and alerts.`, + } + ), + parameters: { + type: 'object', + additionalProperties: false, + properties: { + 'service.environment': { + ...NON_EMPTY_STRING, + description: + 'Optionally filter the services by the environments that they are running in', + }, + start: { + ...NON_EMPTY_STRING, + description: + 'The start of the time range, in Elasticsearch date math, like `now`.', + }, + end: { + ...NON_EMPTY_STRING, + description: + 'The end of the time range, in Elasticsearch date math, like `now-24h`.', + }, + healthStatus: { + type: 'array', + description: 'Filter service list by health status', + additionalProperties: false, + additionalItems: false, + items: { + type: 'string', + enum: [ + ServiceHealthStatus.unknown, + ServiceHealthStatus.healthy, + ServiceHealthStatus.warning, + ServiceHealthStatus.critical, + ], + }, + }, + }, + required: ['start', 'end'], + } as const, + }, + async ({ arguments: args }, signal) => { + return callApmApi('GET /internal/apm/assistant/get_services_list', { + signal, + params: { + query: args, + }, + }); + } + ); +} diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx b/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx index ff215e646148f..9bdfd4b4789d8 100644 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx +++ b/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx @@ -31,6 +31,7 @@ import { getMaxY, getResponseTimeTickFormatter, } from '../components/shared/charts/transaction_charts/helper'; +import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; export function registerGetApmTimeseriesFunction({ registerFunction, @@ -47,7 +48,7 @@ export function registerGetApmTimeseriesFunction({ defaultMessage: `Display different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions`, } ), - description: `Display different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions. In KQL, escaping happens with double quotes, not single quotes. Some characters that need escaping are: ':()\\\/\". Always put a field value in double quotes. Best: service.name:\"opbeans-go\". Wrong: service.name:opbeans-go. This is very important!`, + description: `Visualise and analyse different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. A visualisation will be displayed above your reply - DO NOT attempt to display or generate an image yourself, or any other placeholder. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions.`, parameters: { type: 'object', properties: { @@ -135,11 +136,11 @@ export function registerGetApmTimeseriesFunction({ ], }, 'service.name': { - type: 'string', + ...NON_EMPTY_STRING, description: 'The name of the service', }, 'service.environment': { - type: 'string', + ...NON_EMPTY_STRING, description: 'The environment that the service is running in.', }, @@ -201,7 +202,7 @@ export function registerGetApmTimeseriesFunction({ const groupId = groupSeries[0].group; const maxY = getMaxY(groupSeries); - const latencyFormatter = getDurationFormatter(maxY); + const latencyFormatter = getDurationFormatter(maxY, 10, 1000); let yLabelFormat: (value: number) => string; @@ -230,6 +231,8 @@ export function registerGetApmTimeseriesFunction({ groupSeries.map((series): TimeSeries => { let chartType: ChartType; + const data = series.data; + switch (series.stat.timeseries.name) { case 'transaction_throughput': case 'exit_span_throughput': @@ -270,7 +273,7 @@ export function registerGetApmTimeseriesFunction({ title: series.id, type: 'line', color: getTimeSeriesColor(chartType!).currentPeriodColor, - data: series.data, + data, }; }); diff --git a/x-pack/plugins/apm/public/assistant_functions/index.ts b/x-pack/plugins/apm/public/assistant_functions/index.ts index f83e9fa6fc575..128091cf2472d 100644 --- a/x-pack/plugins/apm/public/assistant_functions/index.ts +++ b/x-pack/plugins/apm/public/assistant_functions/index.ts @@ -18,6 +18,7 @@ import { import { registerGetApmCorrelationsFunction } from './get_apm_correlations'; import { registerGetApmDownstreamDependenciesFunction } from './get_apm_downstream_dependencies'; import { registerGetApmErrorDocumentFunction } from './get_apm_error_document'; +import { registerGetApmServicesListFunction } from './get_apm_services_list'; import { registerGetApmServiceSummaryFunction } from './get_apm_service_summary'; import { registerGetApmTimeseriesFunction } from './get_apm_timeseries'; @@ -64,82 +65,92 @@ export async function registerAssistantFunctions({ registerFunction, }); + registerGetApmServicesListFunction({ + registerFunction, + }); + registerContext({ name: 'apm', description: ` -There are four important data types in Elastic APM. Each of them have the -following fields: -- service.name: the name of the service -- service.node.name: the id of the service instance (often the hostname) -- service.environment: the environment (often production, development) -- agent.name: the name of the agent (go, java, etc) - -The four data types are transactions, exit spans, error events, and application -metrics. - -Transactions have three metrics: throughput, failure rate, and latency. The -fields are: - -- transaction.type: often request or page-load (the main transaction types), -but can also be worker, or route-change. -- transaction.name: The name of the transaction group, often something like -'GET /api/product/:productId' -- transaction.result: The result. Used to capture HTTP response codes -(2xx,3xx,4xx,5xx) for request transactions. -- event.outcome: whether the transaction was succesful or not. success, -failure, or unknown. - -Exit spans have three metrics: throughput, failure rate and latency. The fields -are: -- span.type: db, external -- span.subtype: the type of database (redis, postgres) or protocol (http, grpc) -- span.destination.service.resource: the address of the destination of the call -- event.outcome: whether the transaction was succesful or not. success, -failure, or unknown. - -Error events have one metric, error event rate. The fields are: -- error.grouping_name: a human readable keyword that identifies the error group - -For transaction metrics we also collect anomalies. These are scored 0 (low) to -100 (critical). - -For root cause analysis, locate a change point in the relevant metrics for a -service or downstream dependency. You can locate a change point by using a -sliding window, e.g. start with a small time range, like 30m, and make it -bigger until you identify a change point. It's very important to identify a -change point. If you don't have a change point, ask the user for next steps. -You can also use an anomaly or a deployment as a change point. Then, compare -data before the change with data after the change. You can either use the -groupBy parameter in get_apm_chart to get the most occuring values in a certain -data set, or you can use correlations to see for which field and value the -frequency has changed when comparing the foreground set to the background set. -This is useful when comparing data from before the change point with after the -change point. For instance, you might see a specific error pop up more often -after the change point. - -When comparing anomalies and changes in timeseries, first, zoom in to a smaller -time window, at least 30 minutes before and 30 minutes after the change -occured. E.g., if the anomaly occured at 2023-07-05T08:15:00.000Z, request a -time window that starts at 2023-07-05T07:45:00.000Z and ends at -2023-07-05T08:45:00.000Z. When comparing changes in different timeseries and -anomalies to determine a correlation, make sure to compare the timestamps. If -in doubt, rate the likelihood of them being related, given the time difference, -between 1 and 10. If below 5, assume it's not related. Mention this likelihood -(and the time difference) to the user. - -Your goal is to help the user determine the root cause of an issue quickly and -transparently. If you see a change or -anomaly in a metric for a service, try to find similar changes in the metrics -for the traffic to its downstream dependencies, by comparing transaction -metrics to span metrics. To inspect the traffic from one service to a -downstream dependency, first get the downstream dependencies for a service, -then get the span metrics from that service (\`service.name\`) to its -downstream dependency (\`span.destination.service.resource\`). For instance, -for an anomaly in throughput, first inspect \`transaction_throughput\` for -\`service.name\`. Then, inspect \`exit_span_throughput\` for its downstream -dependencies, by grouping by \`span.destination.service.resource\`. Repeat this -process over the next service its downstream dependencies until you identify a -root cause. If you can not find any similar changes, use correlations or -grouping to find attributes that could be causes for the change.`, + When analyzing APM data, prefer the APM specific functions over the generic Lens, + Elasticsearch or Kibana ones, unless those are explicitly requested by the user. + + When requesting metrics for a service, make sure you also know what environment + it is running in. Metrics aggregated over multiple environments are useless. + + There are four important data types in Elastic APM. Each of them have the + following fields: + - service.name: the name of the service + - service.node.name: the id of the service instance (often the hostname) + - service.environment: the environment (often production, development) + - agent.name: the name of the agent (go, java, etc) + + The four data types are transactions, exit spans, error events, and application + metrics. + + Transactions have three metrics: throughput, failure rate, and latency. The + fields are: + + - transaction.type: often request or page-load (the main transaction types), + but can also be worker, or route-change. + - transaction.name: The name of the transaction group, often something like + 'GET /api/product/:productId' + - transaction.result: The result. Used to capture HTTP response codes + (2xx,3xx,4xx,5xx) for request transactions. + - event.outcome: whether the transaction was succesful or not. success, + failure, or unknown. + + Exit spans have three metrics: throughput, failure rate and latency. The fields + are: + - span.type: db, external + - span.subtype: the type of database (redis, postgres) or protocol (http, grpc) + - span.destination.service.resource: the address of the destination of the call + - event.outcome: whether the transaction was succesful or not. success, + failure, or unknown. + + Error events have one metric, error event rate. The fields are: + - error.grouping_name: a human readable keyword that identifies the error group + + For transaction metrics we also collect anomalies. These are scored 0 (low) to + 100 (critical). + + For root cause analysis, locate a change point in the relevant metrics for a + service or downstream dependency. You can locate a change point by using a + sliding window, e.g. start with a small time range, like 30m, and make it + bigger until you identify a change point. It's very important to identify a + change point. If you don't have a change point, ask the user for next steps. + You can also use an anomaly or a deployment as a change point. Then, compare + data before the change with data after the change. You can either use the + groupBy parameter in get_apm_chart to get the most occuring values in a certain + data set, or you can use correlations to see for which field and value the + frequency has changed when comparing the foreground set to the background set. + This is useful when comparing data from before the change point with after the + change point. For instance, you might see a specific error pop up more often + after the change point. + + When comparing anomalies and changes in timeseries, first, zoom in to a smaller + time window, at least 30 minutes before and 30 minutes after the change + occured. E.g., if the anomaly occured at 2023-07-05T08:15:00.000Z, request a + time window that starts at 2023-07-05T07:45:00.000Z and ends at + 2023-07-05T08:45:00.000Z. When comparing changes in different timeseries and + anomalies to determine a correlation, make sure to compare the timestamps. If + in doubt, rate the likelihood of them being related, given the time difference, + between 1 and 10. If below 5, assume it's not related. Mention this likelihood + (and the time difference) to the user. + + Your goal is to help the user determine the root cause of an issue quickly and + transparently. If you see a change or + anomaly in a metric for a service, try to find similar changes in the metrics + for the traffic to its downstream dependencies, by comparing transaction + metrics to span metrics. To inspect the traffic from one service to a + downstream dependency, first get the downstream dependencies for a service, + then get the span metrics from that service (\`service.name\`) to its + downstream dependency (\`span.destination.service.resource\`). For instance, + for an anomaly in throughput, first inspect \`transaction_throughput\` for + \`service.name\`. Then, inspect \`exit_span_throughput\` for its downstream + dependencies, by grouping by \`span.destination.service.resource\`. Repeat this + process over the next service its downstream dependencies until you identify a + root cause. If you can not find any similar changes, use correlations or + grouping to find attributes that could be causes for the change.`, }); } diff --git a/x-pack/plugins/apm/public/components/alerting/rule_types/error_count_rule_type/index.tsx b/x-pack/plugins/apm/public/components/alerting/rule_types/error_count_rule_type/index.tsx index e302a51f2a5db..b42a3eb3b528f 100644 --- a/x-pack/plugins/apm/public/components/alerting/rule_types/error_count_rule_type/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/rule_types/error_count_rule_type/index.tsx @@ -17,6 +17,7 @@ import { import { EuiFormRow } from '@elastic/eui'; import { EuiSpacer } from '@elastic/eui'; import { EuiSwitchEvent } from '@elastic/eui'; +import { SearchConfigurationType } from '../../../../../common/rules/schema'; import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; import { asInteger } from '../../../../../common/utils/formatters'; import { @@ -58,7 +59,7 @@ export interface ErrorCountRuleParams { groupBy?: string[] | undefined; errorGroupingKey?: string; useKqlFilter?: boolean; - kqlFilter?: string; + searchConfiguration?: SearchConfigurationType; } interface Props { @@ -105,7 +106,7 @@ export function ErrorCountRuleType(props: Props) { start, end, groupBy: params.groupBy, - kqlFilter: params.kqlFilter, + searchConfiguration: JSON.stringify(params.searchConfiguration), }, }, } @@ -119,7 +120,7 @@ export function ErrorCountRuleType(props: Props) { params.serviceName, params.errorGroupingKey, params.groupBy, - params.kqlFilter, + params.searchConfiguration, ] ); @@ -244,7 +245,9 @@ export function ErrorCountRuleType(props: Props) { setRuleParams('serviceName', undefined); setRuleParams('errorGroupingKey', undefined); setRuleParams('environment', ENVIRONMENT_ALL.value); - setRuleParams('kqlFilter', undefined); + setRuleParams('searchConfiguration', { + query: { query: '', language: 'kuery' }, + }); setRuleParams('useKqlFilter', e.target.checked); }; diff --git a/x-pack/plugins/apm/public/components/alerting/rule_types/transaction_duration_rule_type/index.tsx b/x-pack/plugins/apm/public/components/alerting/rule_types/transaction_duration_rule_type/index.tsx index 92c1aa301f516..900f90253a6e1 100644 --- a/x-pack/plugins/apm/public/components/alerting/rule_types/transaction_duration_rule_type/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/rule_types/transaction_duration_rule_type/index.tsx @@ -18,6 +18,7 @@ import { import { EuiFormRow } from '@elastic/eui'; import { EuiSpacer } from '@elastic/eui'; import { EuiSwitchEvent } from '@elastic/eui'; +import { SearchConfigurationType } from '../../../../../common/rules/schema'; import { AggregationType } from '../../../../../common/rules/apm_rule_types'; import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; import { getDurationFormatter } from '../../../../../common/utils/formatters'; @@ -67,7 +68,7 @@ export interface TransactionDurationRuleParams { windowUnit: string; groupBy?: string[] | undefined; useKqlFilter?: boolean; - kqlFilter?: string; + searchConfiguration?: SearchConfigurationType; } const TRANSACTION_ALERT_AGGREGATION_TYPES: Record = { @@ -135,7 +136,7 @@ export function TransactionDurationRuleType(props: Props) { start, end, groupBy: params.groupBy, - kqlFilter: params.kqlFilter, + searchConfiguration: JSON.stringify(params.searchConfiguration), }, }, } @@ -151,7 +152,7 @@ export function TransactionDurationRuleType(props: Props) { params.windowSize, params.windowUnit, params.groupBy, - params.kqlFilter, + params.searchConfiguration, ] ); @@ -314,7 +315,9 @@ export function TransactionDurationRuleType(props: Props) { setRuleParams('transactionType', undefined); setRuleParams('transactionName', undefined); setRuleParams('environment', ENVIRONMENT_ALL.value); - setRuleParams('kqlFilter', undefined); + setRuleParams('searchConfiguration', { + query: { query: '', language: 'kuery' }, + }); setRuleParams('useKqlFilter', e.target.checked); }; diff --git a/x-pack/plugins/apm/public/components/alerting/rule_types/transaction_error_rate_rule_type/index.tsx b/x-pack/plugins/apm/public/components/alerting/rule_types/transaction_error_rate_rule_type/index.tsx index a3032c32521e2..cf1132e58b9e0 100644 --- a/x-pack/plugins/apm/public/components/alerting/rule_types/transaction_error_rate_rule_type/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/rule_types/transaction_error_rate_rule_type/index.tsx @@ -17,6 +17,7 @@ import { import { EuiFormRow } from '@elastic/eui'; import { EuiSpacer } from '@elastic/eui'; import { EuiSwitchEvent } from '@elastic/eui'; +import { SearchConfigurationType } from '../../../../../common/rules/schema'; import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; import { asPercent } from '../../../../../common/utils/formatters'; import { @@ -59,7 +60,7 @@ export interface ErrorRateRuleParams { environment?: string; groupBy?: string[] | undefined; useKqlFilter?: boolean; - kqlFilter?: string; + searchConfiguration?: SearchConfigurationType; } export interface Props { @@ -107,7 +108,7 @@ export function TransactionErrorRateRuleType(props: Props) { start, end, groupBy: params.groupBy, - kqlFilter: params.kqlFilter, + searchConfiguration: JSON.stringify(params.searchConfiguration), }, }, } @@ -122,7 +123,7 @@ export function TransactionErrorRateRuleType(props: Props) { params.windowSize, params.windowUnit, params.groupBy, - params.kqlFilter, + params.searchConfiguration, ] ); @@ -256,7 +257,9 @@ export function TransactionErrorRateRuleType(props: Props) { setRuleParams('transactionType', undefined); setRuleParams('transactionName', undefined); setRuleParams('environment', ENVIRONMENT_ALL.value); - setRuleParams('kqlFilter', undefined); + setRuleParams('searchConfiguration', { + query: { query: '', language: 'kuery' }, + }); setRuleParams('useKqlFilter', e.target.checked); }; diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/apm_rule_kql_filter.tsx b/x-pack/plugins/apm/public/components/alerting/ui_components/apm_rule_kql_filter.tsx index d87e1e3cd995d..9b8e01b2595f4 100644 --- a/x-pack/plugins/apm/public/components/alerting/ui_components/apm_rule_kql_filter.tsx +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/apm_rule_kql_filter.tsx @@ -6,16 +6,15 @@ */ import { i18n } from '@kbn/i18n'; -import React, { useCallback } from 'react'; -import { debounce } from 'lodash'; +import React from 'react'; import { EuiSwitch } from '@elastic/eui'; import { EuiFormRow } from '@elastic/eui'; import { EuiSpacer } from '@elastic/eui'; -import { RuleFlyoutKueryBar } from '@kbn/observability-plugin/public'; -import { useApmDataView } from '../../../hooks/use_apm_data_view'; +import { EuiSwitchEvent } from '@elastic/eui'; import { TransactionDurationRuleParams } from '../rule_types/transaction_duration_rule_type'; import { ErrorRateRuleParams } from '../rule_types/transaction_error_rate_rule_type'; import { ErrorCountRuleParams } from '../rule_types/error_count_rule_type'; +import { ApmRuleUnifiedSearchBar } from './apm_rule_unified_search_bar'; interface Props { ruleParams: @@ -23,7 +22,7 @@ interface Props { | ErrorRateRuleParams | ErrorCountRuleParams; setRuleParams: (key: string, value: any) => void; - onToggleKqlFilter: any; + onToggleKqlFilter: (e: EuiSwitchEvent) => void; } export function ApmRuleKqlFilter({ @@ -31,30 +30,6 @@ export function ApmRuleKqlFilter({ setRuleParams, onToggleKqlFilter, }: Props) { - const FILTER_TYPING_DEBOUNCE_MS = 500; - - const { dataView: derivedIndexPattern } = useApmDataView(); - - const onFilterChange = useCallback( - (filter: string) => { - setRuleParams('kqlFilter', filter); - }, - [setRuleParams] - ); - - /* eslint-disable-next-line react-hooks/exhaustive-deps */ - const debouncedOnFilterChange = useCallback( - debounce(onFilterChange, FILTER_TYPING_DEBOUNCE_MS), - [onFilterChange] - ); - - const placeHolder = i18n.translate( - 'xpack.apm.rule.kqlSearchFieldPlaceholder', - { - defaultMessage: 'Search for APM data… (e.g. service.name: service-1)', - } - ); - const kqlFilterToggle = ( <> ); - const kqlFilter = - ruleParams.useKqlFilter && derivedIndexPattern ? ( - <> - - - - - - ) : null; + const kqlFilter = ruleParams.useKqlFilter ? ( + <> + + + + + + ) : null; return ( <> diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/apm_rule_unified_search_bar.tsx b/x-pack/plugins/apm/public/components/alerting/ui_components/apm_rule_unified_search_bar.tsx new file mode 100644 index 0000000000000..549f394070ce5 --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/apm_rule_unified_search_bar.tsx @@ -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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { Query } from '@kbn/es-query'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { ApmPluginStartDeps } from '../../../plugin'; +import { useApmDataView } from '../../../hooks/use_apm_data_view'; +import { TransactionDurationRuleParams } from '../rule_types/transaction_duration_rule_type'; +import { ErrorRateRuleParams } from '../rule_types/transaction_error_rate_rule_type'; +import { ErrorCountRuleParams } from '../rule_types/error_count_rule_type'; + +export function ApmRuleUnifiedSearchBar({ + placeholder, + ruleParams, + setRuleParams, +}: { + placeholder?: string; + value?: string; + isClearable?: boolean; + ruleParams: + | TransactionDurationRuleParams + | ErrorRateRuleParams + | ErrorCountRuleParams; + setRuleParams: (key: string, value: any) => void; +}) { + const { services } = useKibana(); + + const { + unifiedSearch: { + ui: { SearchBar }, + }, + } = services; + + const { dataView } = useApmDataView(); + const searchbarPlaceholder = + 'Search for APM data… (e.g. service.name: service-1)'; + + const handleSubmit = (payload: { query?: Query }) => { + const { query } = payload; + setRuleParams('searchConfiguration', { query }); + }; + + return ( + + ); +} diff --git a/x-pack/plugins/osquery/cypress/tags.ts b/x-pack/plugins/apm/public/utils/non_empty_string_ref.ts similarity index 69% rename from x-pack/plugins/osquery/cypress/tags.ts rename to x-pack/plugins/apm/public/utils/non_empty_string_ref.ts index a0698a4c40951..94cac08fa2198 100644 --- a/x-pack/plugins/osquery/cypress/tags.ts +++ b/x-pack/plugins/apm/public/utils/non_empty_string_ref.ts @@ -5,8 +5,7 @@ * 2.0. */ -export const tag = { - SERVERLESS: '@serverless', - ESS: '@ess', - BROKEN_IN_SERVERLESS: '@brokenInServerless', +export const NON_EMPTY_STRING = { + type: 'string' as const, + minLength: 1, }; diff --git a/x-pack/plugins/apm/scripts/diagnostics_bundle/diagnostics_bundle.ts b/x-pack/plugins/apm/scripts/diagnostics_bundle/diagnostics_bundle.ts index a620d3e0be017..83671f6b97fc9 100644 --- a/x-pack/plugins/apm/scripts/diagnostics_bundle/diagnostics_bundle.ts +++ b/x-pack/plugins/apm/scripts/diagnostics_bundle/diagnostics_bundle.ts @@ -51,7 +51,6 @@ export async function initDiagnosticsBundle({ const kibanaClient = axios.create({ baseURL: kbHost ?? kibanaHost, auth, - // @ts-expect-error headers: { 'kbn-xsrf': 'true', ...apiKeyHeader }, }); const apmIndices = await getApmIndices(kibanaClient); diff --git a/x-pack/plugins/apm/server/feature.ts b/x-pack/plugins/apm/server/feature.ts index 490c75c658ad9..b34a202376b2a 100644 --- a/x-pack/plugins/apm/server/feature.ts +++ b/x-pack/plugins/apm/server/feature.ts @@ -13,11 +13,17 @@ import { LicensingApiRequestHandlerContext, } from '@kbn/licensing-plugin/server'; import { APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE } from '@kbn/apm-data-access-plugin/server/saved_objects/apm_indices'; +import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/observability-plugin/common/constants'; import { ApmRuleType, APM_SERVER_FEATURE_ID, } from '../common/rules/apm_rule_types'; +const ruleTypes = [ + ...Object.values(ApmRuleType), + OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, +]; + export const APM_FEATURE = { id: APM_SERVER_FEATURE_ID, name: i18n.translate('xpack.apm.featureRegistry.apmFeatureName', { @@ -30,7 +36,7 @@ export const APM_FEATURE = { management: { insightsAndAlerting: ['triggersActions'], }, - alerting: Object.values(ApmRuleType), + alerting: ruleTypes, // see x-pack/plugins/features/common/feature_kibana_privileges.ts privileges: { all: { @@ -43,10 +49,10 @@ export const APM_FEATURE = { }, alerting: { alert: { - all: Object.values(ApmRuleType), + all: ruleTypes, }, rule: { - all: Object.values(ApmRuleType), + all: ruleTypes, }, }, management: { @@ -64,10 +70,10 @@ export const APM_FEATURE = { }, alerting: { alert: { - read: Object.values(ApmRuleType), + read: ruleTypes, }, rule: { - read: Object.values(ApmRuleType), + read: ruleTypes, }, }, management: { diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts index 3054c9f5e8bc7..b5d361777b602 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts @@ -6,164 +6,153 @@ */ import { MakeSchemaFrom } from '@kbn/usage-collection-plugin/server'; -import { - AggregatedTransactionsCounts, - APMUsage, - TimeframeMap, - TimeframeMap1d, - TimeframeMapAll, - APMPerService, -} from './types'; +import { AggregatedTransactionsCounts, APMUsage, APMPerService } from './types'; import { ElasticAgentName } from '../../../typings/es_schemas/ui/fields/agent'; -const long: { type: 'long' } = { type: 'long' }; - -const keyword: { type: 'keyword' } = { type: 'keyword' }; - -const aggregatedTransactionCountSchema: MakeSchemaFrom = - { - expected_metric_document_count: long, - transaction_count: long, - }; - -const timeframeMap1dSchema: MakeSchemaFrom = { - '1d': long, -}; - -const timeframeMapAllSchema: MakeSchemaFrom = { - all: long, -}; - -const timeframeMapSchema: MakeSchemaFrom = { - ...timeframeMap1dSchema, - ...timeframeMapAllSchema, -}; - -const agentSchema: MakeSchemaFrom['agents'][ElasticAgentName] = { - agent: { - version: { - type: 'array', - items: { - type: 'keyword', - _meta: { - description: - 'An array of the top 3 agent versions within the last day', - }, - }, +const aggregatedTransactionCountSchema: MakeSchemaFrom< + AggregatedTransactionsCounts, + true +> = { + expected_metric_document_count: { + type: 'long', + _meta: { + description: '', }, - activation_method: { - type: 'array', - items: { - type: 'keyword', - _meta: { - description: - 'An array of the top 3 agent activation methods within the last day', - }, - }, + }, + transaction_count: { + type: 'long', + _meta: { + description: '', }, }, - service: { - framework: { - name: { - type: 'array', - items: { - type: 'keyword', - _meta: { - description: - 'An array of the top 3 service framework name within the last day', - }, - }, - }, +}; + +const agentSchema: MakeSchemaFrom['agents'][ElasticAgentName] = + { + agent: { version: { type: 'array', items: { type: 'keyword', _meta: { description: - 'An array of the top 3 service framework version within the last day', + 'An array of the top 3 agent versions within the last day', }, }, }, - composite: { + activation_method: { type: 'array', items: { type: 'keyword', _meta: { description: - 'Composite field containing service framework and version sorted by doc count', + 'An array of the top 3 agent activation methods within the last day', }, }, }, }, - language: { - name: { - type: 'array', - items: { - type: 'keyword', - _meta: { - description: - 'An array of the top 3 service language name within the last day', + service: { + framework: { + name: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'An array of the top 3 service framework name within the last day', + }, }, }, - }, - version: { - type: 'array', - items: { - type: 'keyword', - _meta: { - description: - 'An array of the top 3 service language version within the last day', + version: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'An array of the top 3 service framework version within the last day', + }, }, }, - }, - composite: { - type: 'array', - items: { - type: 'keyword', - _meta: { - description: - 'Composite field containing service language name and version sorted by doc count.', + composite: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'Composite field containing service framework and version sorted by doc count', + }, }, }, }, - }, - runtime: { - name: { - type: 'array', - items: { - type: 'keyword', - _meta: { - description: - 'An array of the top 3 service runtime name within the last day', + language: { + name: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'An array of the top 3 service language name within the last day', + }, }, }, - }, - version: { - type: 'array', - items: { - type: 'keyword', - _meta: { - description: - 'An array of the top 3 service runtime version within the last day', + version: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'An array of the top 3 service language version within the last day', + }, + }, + }, + composite: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'Composite field containing service language name and version sorted by doc count.', + }, }, }, }, - composite: { - type: 'array', - items: { - type: 'keyword', - _meta: { - description: - 'Composite field containing service runtime name and version sorted by doc count.', + runtime: { + name: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'An array of the top 3 service runtime name within the last day', + }, + }, + }, + version: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'An array of the top 3 service runtime version within the last day', + }, + }, + }, + composite: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'Composite field containing service runtime name and version sorted by doc count.', + }, }, }, }, }, - }, -}; + }; const apmPerAgentSchema: Pick< - MakeSchemaFrom, + MakeSchemaFrom, 'services_per_agent' | 'agents' > = { // services_per_agent: AGENT_NAMES.reduce( @@ -177,30 +166,174 @@ const apmPerAgentSchema: Pick< // TODO: Find a way for `@kbn/telemetry-tools` to understand and evaluate expressions. // In the meanwhile, we'll have to maintain these lists up to date (TS will remind us to update) services_per_agent: { - 'android/java': long, - dotnet: long, - 'iOS/swift': long, - go: long, - java: long, - 'js-base': long, - nodejs: long, - php: long, - python: long, - ruby: long, - 'rum-js': long, - otlp: long, - 'opentelemetry/cpp': long, - 'opentelemetry/dotnet': long, - 'opentelemetry/erlang': long, - 'opentelemetry/go': long, - 'opentelemetry/java': long, - 'opentelemetry/nodejs': long, - 'opentelemetry/php': long, - 'opentelemetry/python': long, - 'opentelemetry/ruby': long, - 'opentelemetry/rust': long, - 'opentelemetry/swift': long, - 'opentelemetry/webjs': long, + 'android/java': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the android/java agent within the last day', + }, + }, + dotnet: { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the dotnet (.Net) agent within the last day', + }, + }, + 'iOS/swift': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the iOS/swift agent within the last day', + }, + }, + go: { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the go agent within the last day', + }, + }, + java: { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the Java agent within the last day', + }, + }, + 'js-base': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the js-base agent within the last day', + }, + }, + nodejs: { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the nodeJS agent within the last day', + }, + }, + php: { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the PHH agent within the last day', + }, + }, + python: { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the Python agent within the last day', + }, + }, + ruby: { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the Ruby agent within the last day', + }, + }, + 'rum-js': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the rum-js agent within the last day', + }, + }, + otlp: { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the otlp agent within the last day', + }, + }, + 'opentelemetry/cpp': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/cpp agent within the last day', + }, + }, + 'opentelemetry/dotnet': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/dotnet agent within the last day', + }, + }, + 'opentelemetry/erlang': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/erlang agent within the last day', + }, + }, + 'opentelemetry/go': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/go agent within the last day', + }, + }, + 'opentelemetry/java': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/java agent within the last day', + }, + }, + 'opentelemetry/nodejs': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/nodejs agent within the last day', + }, + }, + 'opentelemetry/php': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/php agent within the last day', + }, + }, + 'opentelemetry/python': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/python agent within the last day', + }, + }, + 'opentelemetry/ruby': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/ruby agent within the last day', + }, + }, + 'opentelemetry/rust': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/rust agent within the last day', + }, + }, + 'opentelemetry/swift': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/swift agent within the last day', + }, + }, + 'opentelemetry/webjs': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry/webjs agent within the last day', + }, + }, }, agents: { 'android/java': agentSchema, @@ -217,23 +350,23 @@ const apmPerAgentSchema: Pick< }, }; -export const apmPerServiceSchema: MakeSchemaFrom = { +export const apmPerServiceSchema: MakeSchemaFrom = { service_id: { - ...keyword, + type: 'keyword', _meta: { description: 'Unique identifier that combines the SHA256 hashed representation of the service name and environment', }, }, num_service_nodes: { - ...long, + type: 'long', _meta: { description: 'Total number of the unique service instances that served the transaction within an hour', }, }, num_transaction_types: { - ...long, + type: 'long', _meta: { description: 'Total number of the unique transaction types within an hour', @@ -293,21 +426,21 @@ export const apmPerServiceSchema: MakeSchemaFrom = { }, agent: { name: { - ...keyword, + type: 'keyword', _meta: { description: 'The top value of agent name for the service from transaction documents within an hour. Sorted by _score', }, }, version: { - ...keyword, + type: 'keyword', _meta: { description: 'The top value of agent version for the service from transaction documents within an hour. Sorted by _score', }, }, activation_method: { - ...keyword, + type: 'keyword', _meta: { description: 'The top value of agent activation method for the service from transaction documents within an hour. Sorted by _score', @@ -317,14 +450,14 @@ export const apmPerServiceSchema: MakeSchemaFrom = { service: { language: { name: { - ...keyword, + type: 'keyword', _meta: { description: 'The top value of language name for the service from transaction documents within an hour. Sorted by _score', }, }, version: { - ...keyword, + type: 'keyword', _meta: { description: 'The top value of language version for the service from transaction documents within an hour. Sorted by _score', @@ -333,14 +466,14 @@ export const apmPerServiceSchema: MakeSchemaFrom = { }, framework: { name: { - ...keyword, + type: 'keyword', _meta: { description: 'The top value of service framework name from transaction documents within an hour. Sorted by _score. Example AWS Lambda', }, }, version: { - ...keyword, + type: 'keyword', _meta: { description: 'The top value of service framework version from transaction documents within an hour. Sorted by _score', @@ -349,14 +482,14 @@ export const apmPerServiceSchema: MakeSchemaFrom = { }, runtime: { name: { - ...keyword, + type: 'keyword', _meta: { description: 'The top value of service runtime name from transaction documents within an hour. Sorted by _score', }, }, version: { - ...keyword, + type: 'keyword', _meta: { description: 'The top value of service runtime version version from transaction documents within an hour. Sorted by _score', @@ -367,16 +500,26 @@ export const apmPerServiceSchema: MakeSchemaFrom = { // No data found kubernetes: { pod: { - name: keyword, + name: { + type: 'keyword', + _meta: { + description: 'Kuberneted pod name ', + }, + }, }, }, // No data found container: { - id: keyword, + id: { + type: 'keyword', + _meta: { + description: 'Container id', + }, + }, }, }; -export const apmSchema: MakeSchemaFrom = { +export const apmSchema: MakeSchemaFrom = { ...apmPerAgentSchema, has_any_services: { type: 'boolean', @@ -388,19 +531,19 @@ export const apmSchema: MakeSchemaFrom = { version: { apm_server: { major: { - ...long, + type: 'long', _meta: { description: 'The major version of the APM server. Example: 7', }, }, minor: { - ...long, + type: 'long', _meta: { description: 'The minor version of the APM server. Example: 17', }, }, patch: { - ...long, + type: 'long', _meta: { description: 'The patch version of the APM server. Example 3', }, @@ -409,14 +552,14 @@ export const apmSchema: MakeSchemaFrom = { }, environments: { services_without_environment: { - ...long, + type: 'long', _meta: { description: 'Number of services without an assigned environment within the last day. This is determined by checking the "service.environment" field and counting instances where it is null', }, }, services_with_multiple_environments: { - ...long, + type: 'long', _meta: { description: 'Number of services with more than one assigned environment within the last day', @@ -433,7 +576,6 @@ export const apmSchema: MakeSchemaFrom = { }, }, }, - // #NOTE No task identified for extracting the following information aggregated_transactions: { current_implementation: aggregatedTransactionCountSchema, no_observer_name: aggregatedTransactionCountSchema, @@ -491,14 +633,14 @@ export const apmSchema: MakeSchemaFrom = { counts: { transaction: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of transaction documents within the last day', }, }, all: { - ...long, + type: 'long', _meta: { description: 'Total number of transaction documents overall', }, @@ -506,13 +648,13 @@ export const apmSchema: MakeSchemaFrom = { }, span: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of span documents within the last day', }, }, all: { - ...long, + type: 'long', _meta: { description: 'Total number of span documents overall', }, @@ -520,13 +662,13 @@ export const apmSchema: MakeSchemaFrom = { }, error: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of error documents within the last day', }, }, all: { - ...long, + type: 'long', _meta: { description: 'Total number of error documents overall', }, @@ -534,13 +676,13 @@ export const apmSchema: MakeSchemaFrom = { }, metric: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of metric documents within the last day', }, }, all: { - ...long, + type: 'long', _meta: { description: 'Total number of metric documents overall', }, @@ -548,14 +690,14 @@ export const apmSchema: MakeSchemaFrom = { }, onboarding: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of onboarding documents within the last day', }, }, all: { - ...long, + type: 'long', _meta: { description: 'Total number of onboarding documents overall', }, @@ -563,7 +705,7 @@ export const apmSchema: MakeSchemaFrom = { }, agent_configuration: { all: { - ...long, + type: 'long', _meta: { description: 'Total number of apm-agent-configuration documents overall', @@ -572,7 +714,7 @@ export const apmSchema: MakeSchemaFrom = { }, max_transaction_groups_per_service: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of distinct transaction groups for the top service for the last 24 hours', @@ -581,7 +723,7 @@ export const apmSchema: MakeSchemaFrom = { }, max_error_groups_per_service: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of distinct error groups for the top service for the last 24 hours', @@ -590,23 +732,29 @@ export const apmSchema: MakeSchemaFrom = { }, traces: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of trace documents within the last day', }, }, all: { - ...long, + type: 'long', _meta: { description: 'Total number of trace documents overall', }, }, }, - // No tasks found - services: timeframeMapSchema, + services: { + '1d': { + type: 'long', + _meta: { + description: 'Total number of unique services within the last day', + }, + }, + }, environments: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of unique environments within the last day', @@ -615,7 +763,7 @@ export const apmSchema: MakeSchemaFrom = { }, span_destination_service_resource: { '1d': { - ...long, + type: 'long', _meta: { description: 'Total number of unique values of span.destination.service.resource within the last day', @@ -630,7 +778,7 @@ export const apmSchema: MakeSchemaFrom = { country_iso_code: { rum: { '1d': { - ...long, + type: 'long', _meta: { description: 'Unique country iso code captured for the agents js-base, rum-js and opentelemetry/webjs within the last day', @@ -644,7 +792,7 @@ export const apmSchema: MakeSchemaFrom = { original: { all_agents: { '1d': { - ...long, + type: 'long', _meta: { description: 'Unique user agent for all agents within the last day', @@ -653,7 +801,7 @@ export const apmSchema: MakeSchemaFrom = { }, rum: { '1d': { - ...long, + type: 'long', _meta: { description: 'Unique user agent for rum agent within the last day', @@ -666,7 +814,7 @@ export const apmSchema: MakeSchemaFrom = { name: { all_agents: { '1d': { - ...long, + type: 'long', _meta: { description: 'Unique transaction names for all agents within the last day', @@ -675,7 +823,7 @@ export const apmSchema: MakeSchemaFrom = { }, rum: { '1d': { - ...long, + type: 'long', _meta: { description: 'Unique transaction names for rum agent within the last day', @@ -689,7 +837,7 @@ export const apmSchema: MakeSchemaFrom = { retainment: { span: { ms: { - ...long, + type: 'long', _meta: { description: 'Represent the time difference in milliseconds between the current date and the date when the span document was recorded', @@ -698,7 +846,7 @@ export const apmSchema: MakeSchemaFrom = { }, transaction: { ms: { - ...long, + type: 'long', _meta: { description: 'Represent the time difference in milliseconds between the current date and the date when the transaction document was recorded', @@ -707,7 +855,7 @@ export const apmSchema: MakeSchemaFrom = { }, error: { ms: { - ...long, + type: 'long', _meta: { description: 'Represent the time difference in milliseconds between the current date and the date when the error document was recorded', @@ -716,7 +864,7 @@ export const apmSchema: MakeSchemaFrom = { }, metric: { ms: { - ...long, + type: 'long', _meta: { description: 'Represent the time difference in milliseconds between the current date and the date when the metric document was recorded', @@ -725,7 +873,7 @@ export const apmSchema: MakeSchemaFrom = { }, onboarding: { ms: { - ...long, + type: 'long', _meta: { description: 'Represent the time difference in milliseconds between the current date and the date when the onboarding document was recorded', @@ -736,7 +884,7 @@ export const apmSchema: MakeSchemaFrom = { integrations: { ml: { all_jobs_count: { - ...long, + type: 'long', _meta: { description: 'Total number of anomaly detection jobs associated with the jobs apm-*, *-high_mean_response_time', @@ -746,23 +894,44 @@ export const apmSchema: MakeSchemaFrom = { }, indices: { - // cannot find related data metric: { - shards: { total: long }, + shards: { + total: { + type: 'long', + _meta: { + description: 'Total number of shards for metric indices', + }, + }, + }, all: { total: { - docs: { count: long }, - store: { size_in_bytes: long }, + docs: { + count: { + type: 'long', + _meta: { + description: 'Total number of metric documents overall', + }, + }, + }, + store: { + size_in_bytes: { + type: 'long', + _meta: { + description: + 'Size of the metric indicess in byte units overall.', + }, + }, + }, }, }, }, - // cannot find related data traces: { shards: { total: { - ...long, + type: 'long', _meta: { - description: 'Total number of shards overall', + description: + 'Total number of shards for span and trasnaction indices', }, }, }, @@ -770,7 +939,7 @@ export const apmSchema: MakeSchemaFrom = { total: { docs: { count: { - ...long, + type: 'long', _meta: { description: 'Total number of transaction and span documents overall', @@ -779,7 +948,7 @@ export const apmSchema: MakeSchemaFrom = { }, store: { size_in_bytes: { - ...long, + type: 'long', _meta: { description: 'Size of the index in byte units overall.', }, @@ -790,7 +959,7 @@ export const apmSchema: MakeSchemaFrom = { }, shards: { total: { - ...long, + type: 'long', _meta: { description: 'Total number of shards overall', }, @@ -800,7 +969,7 @@ export const apmSchema: MakeSchemaFrom = { total: { docs: { count: { - ...long, + type: 'long', _meta: { description: 'Total number of all documents overall', }, @@ -808,7 +977,7 @@ export const apmSchema: MakeSchemaFrom = { }, store: { size_in_bytes: { - ...long, + type: 'long', _meta: { description: 'Size of the index in byte units overall.', }, @@ -829,7 +998,7 @@ export const apmSchema: MakeSchemaFrom = { }, }, total: { - ...long, + type: 'long', _meta: { description: 'Total number of service groups retrived from the saved object across all spaces', @@ -841,7 +1010,7 @@ export const apmSchema: MakeSchemaFrom = { aggregated_transactions: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "aggregated_transactions" task', @@ -852,7 +1021,7 @@ export const apmSchema: MakeSchemaFrom = { cloud: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "cloud" task', }, @@ -862,7 +1031,7 @@ export const apmSchema: MakeSchemaFrom = { host: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "host" task', }, @@ -872,7 +1041,7 @@ export const apmSchema: MakeSchemaFrom = { processor_events: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "processor_events" task', @@ -883,7 +1052,7 @@ export const apmSchema: MakeSchemaFrom = { agent_configuration: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "agent_configuration" task', @@ -894,7 +1063,7 @@ export const apmSchema: MakeSchemaFrom = { services: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "services" task', @@ -905,7 +1074,7 @@ export const apmSchema: MakeSchemaFrom = { versions: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "versions" task', @@ -916,7 +1085,7 @@ export const apmSchema: MakeSchemaFrom = { groupings: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "groupings" task', @@ -927,7 +1096,7 @@ export const apmSchema: MakeSchemaFrom = { integrations: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "integrations" task', @@ -938,7 +1107,7 @@ export const apmSchema: MakeSchemaFrom = { agents: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "agents" task', }, @@ -948,7 +1117,7 @@ export const apmSchema: MakeSchemaFrom = { indices_stats: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "indices_stats" task', @@ -959,7 +1128,7 @@ export const apmSchema: MakeSchemaFrom = { cardinality: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "cardinality" task', @@ -970,7 +1139,7 @@ export const apmSchema: MakeSchemaFrom = { environments: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "environments" task', @@ -981,7 +1150,7 @@ export const apmSchema: MakeSchemaFrom = { service_groups: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "service_groups" task', @@ -992,7 +1161,7 @@ export const apmSchema: MakeSchemaFrom = { per_service: { took: { ms: { - ...long, + type: 'long', _meta: { description: 'Execution time in milliseconds for the "per_service" task', diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts index e88e021fbd0cb..9c6c312c284f4 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts @@ -107,7 +107,7 @@ export interface APMUsage { max_transaction_groups_per_service: TimeframeMap1d; max_error_groups_per_service: TimeframeMap1d; traces: TimeframeMap; - services: TimeframeMap; + services: TimeframeMap1d; environments: TimeframeMap1d; span_destination_service_resource: TimeframeMap1d; }; diff --git a/x-pack/plugins/apm/server/routes/alerts/route.ts b/x-pack/plugins/apm/server/routes/alerts/route.ts index 67470d19180ce..3343b7f78f0af 100644 --- a/x-pack/plugins/apm/server/routes/alerts/route.ts +++ b/x-pack/plugins/apm/server/routes/alerts/route.ts @@ -6,6 +6,7 @@ */ import * as t from 'io-ts'; +import { jsonRt } from '@kbn/io-ts-utils'; import { Coordinate } from '../../../typings/timeseries'; import { getTransactionDurationChartPreview } from './rule_types/transaction_duration/get_transaction_duration_chart_preview'; import { getTransactionErrorCountChartPreview } from './rule_types/error_count/get_error_count_chart_preview'; @@ -15,6 +16,13 @@ import { environmentRt, rangeRt } from '../default_api_types'; import { AggregationType } from '../../../common/rules/apm_rule_types'; import { getApmEventClient } from '../../lib/helpers/get_apm_event_client'; +const searchConfigurationRt = t.type({ + query: t.type({ + query: t.union([t.string, t.record(t.string, t.any)]), + language: t.string, + }), +}); + const alertParamsRt = t.intersection([ t.partial({ aggregationType: t.union([ @@ -34,7 +42,7 @@ const alertParamsRt = t.intersection([ }), t.partial({ groupBy: t.array(t.string), - kqlFilter: t.string, + searchConfiguration: jsonRt.pipe(searchConfigurationRt), }), ]); diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/get_error_count_chart_preview.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/get_error_count_chart_preview.ts index e1bf2ba2b7a43..a1fcb98d7a323 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/get_error_count_chart_preview.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/get_error_count_chart_preview.ts @@ -42,7 +42,7 @@ export async function getTransactionErrorCountChartPreview({ start, end, groupBy: groupByFields, - kqlFilter, + searchConfiguration, } = alertParams; const allGroupByFields = getAllGroupByFields( @@ -50,7 +50,7 @@ export async function getTransactionErrorCountChartPreview({ groupByFields ); - const termFilterQuery = !kqlFilter + const termFilterQuery = !searchConfiguration ? [ ...termQuery(SERVICE_NAME, serviceName, { queryEmptyString: false, @@ -66,7 +66,7 @@ export async function getTransactionErrorCountChartPreview({ bool: { filter: [ ...termFilterQuery, - ...getParsedFilterQuery(kqlFilter), + ...getParsedFilterQuery(searchConfiguration?.query?.query as string), ...rangeQuery(start, end), { term: { [PROCESSOR_EVENT]: ProcessorEvent.error } }, ], diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.test.ts index cc509c41fb8b2..1b56d89d91d3a 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.test.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.test.ts @@ -709,7 +709,12 @@ describe('Error count alert', () => { windowSize: 5, windowUnit: 'm', serviceName: undefined, - kqlFilter: 'service.name: foo and service.environment: env-foo', + searchConfiguration: { + query: { + query: 'service.name: foo and service.environment: env-foo', + language: 'kuery', + }, + }, groupBy: ['service.name', 'service.environment'], }; diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.ts index 1049df62f8043..f0843516e4c9a 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.ts @@ -117,7 +117,7 @@ export function registerErrorCountRuleType({ const indices = await getApmIndices(savedObjectsClient); - const termFilterQuery = !ruleParams.kqlFilter + const termFilterQuery = !ruleParams.searchConfiguration ? [ ...termQuery(SERVICE_NAME, ruleParams.serviceName, { queryEmptyString: false, @@ -146,7 +146,9 @@ export function registerErrorCountRuleType({ }, { term: { [PROCESSOR_EVENT]: ProcessorEvent.error } }, ...termFilterQuery, - ...getParsedFilterQuery(ruleParams.kqlFilter), + ...getParsedFilterQuery( + ruleParams.searchConfiguration?.query?.query as string + ), ], }, }, diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/get_transaction_duration_chart_preview.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/get_transaction_duration_chart_preview.ts index 12df75f19334b..bf191c5213cf0 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/get_transaction_duration_chart_preview.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/get_transaction_duration_chart_preview.ts @@ -60,7 +60,7 @@ export async function getTransactionDurationChartPreview({ start, end, groupBy: groupByFields, - kqlFilter, + searchConfiguration, } = alertParams; const searchAggregatedTransactions = await getSearchTransactionsEvents({ config, @@ -68,7 +68,7 @@ export async function getTransactionDurationChartPreview({ kuery: '', }); - const termFilterQuery = !kqlFilter + const termFilterQuery = !searchConfiguration ? [ ...termQuery(SERVICE_NAME, serviceName, { queryEmptyString: false, @@ -87,7 +87,7 @@ export async function getTransactionDurationChartPreview({ bool: { filter: [ ...termFilterQuery, - ...getParsedFilterQuery(kqlFilter), + ...getParsedFilterQuery(searchConfiguration?.query?.query as string), ...rangeQuery(start, end), ...getDocumentTypeFilterForTransactions(searchAggregatedTransactions), ] as QueryDslQueryContainer[], diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.test.ts index 1e62211e3f19a..33aba72eb96be 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.test.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.test.ts @@ -327,7 +327,12 @@ describe('registerTransactionDurationRuleType', () => { transactionType: undefined, serviceName: undefined, aggregationType: 'avg', - kqlFilter: 'service.name: opbeans-java and transaction.type: request', + searchConfiguration: { + query: { + query: 'service.name: opbeans-java and transaction.type: request', + language: 'kuery', + }, + }, groupBy: ['service.name', 'service.environment', 'transaction.type'], }; diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.ts index 0690e04dcf47e..7a1beb3ba9f9e 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.ts @@ -135,7 +135,7 @@ export function registerTransactionDurationRuleType({ searchAggregatedTransactions ); - const termFilterQuery = !ruleParams.kqlFilter + const termFilterQuery = !ruleParams.searchConfiguration ? [ ...termQuery(SERVICE_NAME, ruleParams.serviceName, { queryEmptyString: false, @@ -169,7 +169,9 @@ export function registerTransactionDurationRuleType({ searchAggregatedTransactions ), ...termFilterQuery, - ...getParsedFilterQuery(ruleParams.kqlFilter), + ...getParsedFilterQuery( + ruleParams.searchConfiguration?.query?.query as string + ), ] as QueryDslQueryContainer[], }, }, diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/get_transaction_error_rate_chart_preview.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/get_transaction_error_rate_chart_preview.ts index e2f3888455f96..3ffa001fccc9d 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/get_transaction_error_rate_chart_preview.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/get_transaction_error_rate_chart_preview.ts @@ -52,7 +52,7 @@ export async function getTransactionErrorRateChartPreview({ end, transactionName, groupBy: groupByFields, - kqlFilter, + searchConfiguration, } = alertParams; const searchAggregatedTransactions = await getSearchTransactionsEvents({ @@ -66,7 +66,7 @@ export async function getTransactionErrorRateChartPreview({ groupByFields ); - const termFilterQuery = !kqlFilter + const termFilterQuery = !searchConfiguration ? [ ...termQuery(SERVICE_NAME, serviceName, { queryEmptyString: false, @@ -92,7 +92,9 @@ export async function getTransactionErrorRateChartPreview({ bool: { filter: [ ...termFilterQuery, - ...getParsedFilterQuery(kqlFilter), + ...getParsedFilterQuery( + searchConfiguration?.query?.query as string + ), ...rangeQuery(start, end), ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.test.ts index 4f779ca4d7412..e565ce69a538e 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.test.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.test.ts @@ -481,8 +481,13 @@ describe('Transaction error rate alert', () => { threshold: 10, windowSize: 5, windowUnit: 'm', - kqlFilter: - 'service.name: bar and service.environment: env-bar and transaction.type: type-bar', + searchConfiguration: { + query: { + query: + 'service.name: bar and service.environment: env-bar and transaction.type: type-bar', + language: 'kuery', + }, + }, groupBy: ['service.name', 'service.environment', 'transaction.type'], }; diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.ts index afc2deb976099..7015862db8d9e 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.ts @@ -137,7 +137,7 @@ export function registerTransactionErrorRateRuleType({ ? indices.metric : indices.transaction; - const termFilterQuery = !ruleParams.kqlFilter + const termFilterQuery = !ruleParams.searchConfiguration ? [ ...termQuery(SERVICE_NAME, ruleParams.serviceName, { queryEmptyString: false, @@ -179,7 +179,9 @@ export function registerTransactionErrorRateRuleType({ }, }, ...termFilterQuery, - ...getParsedFilterQuery(ruleParams.kqlFilter), + ...getParsedFilterQuery( + ruleParams.searchConfiguration?.query?.query as string + ), ], }, }, diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_error_event_rate.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_error_event_rate.ts index 85debffb41742..9022d4fc87e4b 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_error_event_rate.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_error_event_rate.ts @@ -6,7 +6,6 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { RollupInterval } from '../../../../common/rollup'; import type { APMEventClient } from '../../../lib/helpers/create_es_client/create_apm_event_client'; @@ -40,7 +39,7 @@ export async function getErrorEventRate({ documentType: ApmDocumentType.ErrorEvent, rollupInterval: RollupInterval.None, intervalString, - filter: filter.concat(...rangeQuery(start, end)), + filter, aggs: { value: { bucket_script: { diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_failure_rate.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_failure_rate.ts index 655d03dd87448..35ca607e9e338 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_failure_rate.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_failure_rate.ts @@ -6,7 +6,7 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { EVENT_OUTCOME, @@ -45,7 +45,6 @@ export async function getExitSpanFailureRate({ rollupInterval: RollupInterval.OneMinute, intervalString, filter: filter.concat( - ...rangeQuery(start, end), ...termQuery( SPAN_DESTINATION_SERVICE_RESOURCE, spanDestinationServiceResource diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_latency.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_latency.ts index 1d5bcd04cd35c..ad1f8cb8791be 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_latency.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_latency.ts @@ -6,7 +6,7 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { SPAN_DESTINATION_SERVICE_RESOURCE, @@ -39,12 +39,11 @@ export async function getExitSpanLatency({ start, end, operationName: 'assistant_get_exit_span_latency', - unit: 'rpm', + unit: 'ms', documentType: ApmDocumentType.ServiceDestinationMetric, rollupInterval: RollupInterval.OneMinute, intervalString, filter: filter.concat( - ...rangeQuery(start, end), ...termQuery( SPAN_DESTINATION_SERVICE_RESOURCE, spanDestinationServiceResource diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_throughput.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_throughput.ts index dd49c4c7d79f4..ab1be9d2c20dc 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_throughput.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_exit_span_throughput.ts @@ -6,7 +6,7 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { SPAN_DESTINATION_SERVICE_RESOURCE } from '../../../../common/es_fields/apm'; import { RollupInterval } from '../../../../common/rollup'; @@ -44,7 +44,6 @@ export async function getExitSpanThroughput({ rollupInterval: RollupInterval.OneMinute, intervalString, filter: filter.concat( - ...rangeQuery(start, end), ...termQuery( SPAN_DESTINATION_SERVICE_RESOURCE, spanDestinationServiceResource @@ -73,7 +72,7 @@ export async function getExitSpanThroughput({ ...fetchedSerie, value: fetchedSerie.value !== null - ? fetchedSerie.value / rangeInMinutes + ? (fetchedSerie.value * bucketSizeInMinutes) / rangeInMinutes : null, data: fetchedSerie.data.map((bucket) => { return { diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_failure_rate.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_failure_rate.ts index b4b0704ce6ea9..8e44eac64e3e9 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_failure_rate.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_failure_rate.ts @@ -6,7 +6,7 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { TRANSACTION_TYPE } from '../../../../common/es_fields/apm'; import { RollupInterval } from '../../../../common/rollup'; @@ -40,10 +40,7 @@ export async function getTransactionFailureRate({ documentType: ApmDocumentType.TransactionMetric, rollupInterval: RollupInterval.OneMinute, intervalString, - filter: filter.concat( - ...rangeQuery(start, end), - ...termQuery(TRANSACTION_TYPE, transactionType) - ), + filter: filter.concat(...termQuery(TRANSACTION_TYPE, transactionType)), groupBy: 'transaction.type', aggs: { ...getOutcomeAggregation(ApmDocumentType.TransactionMetric), diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_latency.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_latency.ts index 8cbb6dd74d2d9..f51378c647fd4 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_latency.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_latency.ts @@ -6,7 +6,7 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { TRANSACTION_DURATION_HISTOGRAM, @@ -41,15 +41,12 @@ export async function getTransactionLatency({ apmEventClient, start, end, - operationName: 'assistant_get_transaction_latencyu', - unit: 'rpm', + operationName: 'assistant_get_transaction_latency', + unit: 'ms', documentType: ApmDocumentType.TransactionMetric, rollupInterval: RollupInterval.OneMinute, intervalString, - filter: filter.concat( - ...rangeQuery(start, end), - ...termQuery(TRANSACTION_TYPE, transactionType) - ), + filter: filter.concat(...termQuery(TRANSACTION_TYPE, transactionType)), groupBy: 'transaction.type', aggs: { ...getLatencyAggregation( diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_throughput.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_throughput.ts index 919f2b63e5165..891ebd8b6a356 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_throughput.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_timeseries/get_transaction_throughput.ts @@ -6,7 +6,7 @@ */ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { rangeQuery, termQuery } from '@kbn/observability-plugin/server'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ApmDocumentType } from '../../../../common/document_type'; import { TRANSACTION_TYPE } from '../../../../common/es_fields/apm'; import { RollupInterval } from '../../../../common/rollup'; @@ -43,10 +43,7 @@ export async function getTransactionThroughput({ documentType: ApmDocumentType.TransactionMetric, rollupInterval: RollupInterval.OneMinute, intervalString, - filter: filter.concat( - ...rangeQuery(start, end), - ...termQuery(TRANSACTION_TYPE, transactionType) - ), + filter: filter.concat(...termQuery(TRANSACTION_TYPE, transactionType)), groupBy: 'transaction.type', aggs: { value: { @@ -70,7 +67,7 @@ export async function getTransactionThroughput({ ...fetchedSerie, value: fetchedSerie.value !== null - ? fetchedSerie.value / rangeInMinutes + ? (fetchedSerie.value * bucketSizeInMinutes) / rangeInMinutes : null, data: fetchedSerie.data.map((bucket) => { return { diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/route.ts b/x-pack/plugins/apm/server/routes/assistant_functions/route.ts index bd2d32c90907e..486fdb57fca84 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/route.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/route.ts @@ -4,14 +4,22 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import datemath from '@elastic/datemath'; import { ElasticsearchClient } from '@kbn/core/server'; import * as t from 'io-ts'; import { omit } from 'lodash'; +import { ApmDocumentType } from '../../../common/document_type'; +import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; +import { RollupInterval } from '../../../common/rollup'; +import { ServiceHealthStatus } from '../../../common/service_health_status'; import type { APMError } from '../../../typings/es_schemas/ui/apm_error'; import { getApmAlertsClient } from '../../lib/helpers/get_apm_alerts_client'; import { getApmEventClient } from '../../lib/helpers/get_apm_event_client'; import { getMlClient } from '../../lib/helpers/get_ml_client'; +import { getRandomSampler } from '../../lib/helpers/get_random_sampler'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { environmentRt } from '../default_api_types'; +import { getServicesItems } from '../services/get_services/get_services_items'; import { CorrelationValue, correlationValuesRouteRt, @@ -184,10 +192,105 @@ const getApmErrorDocRoute = createApmServerRoute({ }, }); +interface ApmServicesListItem { + 'service.name': string; + 'agent.name'?: string; + 'transaction.type'?: string; + alertsCount: number; + healthStatus: ServiceHealthStatus; + 'service.environment'?: string[]; +} + +type ApmServicesListContent = ApmServicesListItem[]; + +const getApmServicesListRoute = createApmServerRoute({ + endpoint: 'GET /internal/apm/assistant/get_services_list', + params: t.type({ + query: t.intersection([ + t.type({ + start: t.string, + end: t.string, + }), + t.partial({ + 'service.environment': environmentRt.props.environment, + healthStatus: t.array( + t.union([ + t.literal(ServiceHealthStatus.unknown), + t.literal(ServiceHealthStatus.healthy), + t.literal(ServiceHealthStatus.warning), + t.literal(ServiceHealthStatus.critical), + ]) + ), + }), + ]), + }), + options: { + tags: ['access:apm'], + }, + handler: async (resources): Promise<{ content: ApmServicesListContent }> => { + const { params } = resources; + const { query } = params; + + const { healthStatus } = query; + + const [apmEventClient, apmAlertsClient, mlClient, randomSampler] = + await Promise.all([ + getApmEventClient(resources), + getApmAlertsClient(resources), + getMlClient(resources), + getRandomSampler({ + security: resources.plugins.security, + probability: 1, + request: resources.request, + }), + ]); + + const start = datemath.parse(query.start)?.valueOf()!; + const end = datemath.parse(query.end)?.valueOf()!; + + const serviceItems = await getServicesItems({ + apmAlertsClient, + apmEventClient, + documentType: ApmDocumentType.TransactionMetric, + start, + end, + environment: query['service.environment'] ?? ENVIRONMENT_ALL.value, + kuery: '', + logger: resources.logger, + randomSampler, + rollupInterval: RollupInterval.OneMinute, + serviceGroup: null, + mlClient, + }); + + let mappedItems = serviceItems.items.map((item): ApmServicesListItem => { + return { + 'service.name': item.serviceName, + 'agent.name': item.agentName, + alertsCount: item.alertsCount ?? 0, + healthStatus: item.healthStatus ?? ServiceHealthStatus.unknown, + 'service.environment': item.environments, + 'transaction.type': item.transactionType, + }; + }); + + if (healthStatus && healthStatus.length) { + mappedItems = mappedItems.filter((item): boolean => + healthStatus.includes(item.healthStatus) + ); + } + + return { + content: mappedItems, + }; + }, +}); + export const assistantRouteRepository = { ...getApmTimeSeriesRoute, ...getApmServiceSummaryRoute, ...getApmErrorDocRoute, ...getApmCorrelationValuesRoute, ...getDownstreamDependenciesRoute, + ...getApmServicesListRoute, }; diff --git a/x-pack/plugins/apm_data_access/server/index.ts b/x-pack/plugins/apm_data_access/server/index.ts index 4d7ae2b1eb6c3..4ef9a47937733 100644 --- a/x-pack/plugins/apm_data_access/server/index.ts +++ b/x-pack/plugins/apm_data_access/server/index.ts @@ -16,6 +16,7 @@ const configSchema = schema.object({ error: schema.string({ defaultValue: 'logs-apm*,apm-*' }), metric: schema.string({ defaultValue: 'metrics-apm*,apm-*' }), onboarding: schema.string({ defaultValue: 'apm-*' }), // Unused: to be deleted + sourcemap: schema.string({ defaultValue: 'apm-*' }), // Unused: to be deleted }), }); @@ -23,7 +24,11 @@ const configSchema = schema.object({ export const config: PluginConfigDescriptor = { deprecations: ({ renameFromRoot, unused, deprecate }) => [ // deprecations - unused('indices.sourcemap', { level: 'warning' }), + deprecate('indices.sourcemap', 'a future version', { + level: 'warning', + message: `Configuring "xpack.apm.indices.sourcemap" is deprecated and will be removed in a future version. Please remove this setting.`, + }), + deprecate('indices.onboarding', 'a future version', { level: 'warning', message: `Configuring "xpack.apm.indices.onboarding" is deprecated and will be removed in a future version. Please remove this setting.`, diff --git a/x-pack/plugins/cases/common/index.ts b/x-pack/plugins/cases/common/index.ts index fdd10cbb5bf94..4283adf4c081a 100644 --- a/x-pack/plugins/cases/common/index.ts +++ b/x-pack/plugins/cases/common/index.ts @@ -50,13 +50,15 @@ export { INTERNAL_BULK_CREATE_ATTACHMENTS_URL, SAVED_OBJECT_TYPES, CASE_COMMENT_SAVED_OBJECT, + CASES_CONNECTORS_CAPABILITY, + GET_CONNECTORS_CONFIGURE_API_TAG, } from './constants'; export type { AttachmentAttributes } from './types/domain'; export { ConnectorTypes, AttachmentType, ExternalReferenceStorageType } from './types/domain'; export { getCasesFromAlertsUrl, getCaseFindUserActionsUrl, throwErrors } from './api'; export { StatusAll } from './ui/types'; -export { createUICapabilities } from './utils/capabilities'; -export { getApiTags } from './utils/api_tags'; +export { createUICapabilities, type CasesUiCapabilities } from './utils/capabilities'; +export { getApiTags, type CasesApiTags } from './utils/api_tags'; export { CaseMetricsFeature } from './types/api'; export type { SingleCaseMetricsResponse, CasesMetricsResponse } from './types/api'; diff --git a/x-pack/plugins/cases/common/utils/api_tags.ts b/x-pack/plugins/cases/common/utils/api_tags.ts index 2568c0e79b9a0..3fbad714e55f9 100644 --- a/x-pack/plugins/cases/common/utils/api_tags.ts +++ b/x-pack/plugins/cases/common/utils/api_tags.ts @@ -14,7 +14,13 @@ import { HttpApiTagOperation } from '../constants/types'; import type { Owner } from '../constants/types'; import { constructFilesHttpOperationTag } from '../files'; -export const getApiTags = (owner: Owner) => { +export interface CasesApiTags { + all: readonly string[]; + read: readonly string[]; + delete: readonly string[]; +} + +export const getApiTags = (owner: Owner): CasesApiTags => { const create = constructFilesHttpOperationTag(owner, HttpApiTagOperation.Create); const deleteTag = constructFilesHttpOperationTag(owner, HttpApiTagOperation.Delete); const read = constructFilesHttpOperationTag(owner, HttpApiTagOperation.Read); diff --git a/x-pack/plugins/cases/common/utils/capabilities.ts b/x-pack/plugins/cases/common/utils/capabilities.ts index e9c05eda47171..28b3fa00f9272 100644 --- a/x-pack/plugins/cases/common/utils/capabilities.ts +++ b/x-pack/plugins/cases/common/utils/capabilities.ts @@ -14,11 +14,16 @@ import { UPDATE_CASES_CAPABILITY, } from '../constants'; +export interface CasesUiCapabilities { + all: readonly string[]; + read: readonly string[]; + delete: readonly string[]; +} /** * Return the UI capabilities for each type of operation. These strings must match the values defined in the UI * here: x-pack/plugins/cases/public/client/helpers/capabilities.ts */ -export const createUICapabilities = () => ({ +export const createUICapabilities = (): CasesUiCapabilities => ({ all: [ CREATE_CASES_CAPABILITY, READ_CASES_CAPABILITY, diff --git a/x-pack/plugins/cases/server/client/mocks.ts b/x-pack/plugins/cases/server/client/mocks.ts index f912ce26f581e..8fd0a61c35f30 100644 --- a/x-pack/plugins/cases/server/client/mocks.ts +++ b/x-pack/plugins/cases/server/client/mocks.ts @@ -11,7 +11,7 @@ import type { ISavedObjectsSerializer } from '@kbn/core-saved-objects-server'; import { createFileServiceMock } from '@kbn/files-plugin/server/mocks'; import { securityMock } from '@kbn/security-plugin/server/mocks'; -import { actionsClientMock } from '@kbn/actions-plugin/server/actions_client.mock'; +import { actionsClientMock } from '@kbn/actions-plugin/server/actions_client/actions_client.mock'; import { makeLensEmbeddableFactory } from '@kbn/lens-plugin/server/embeddable/make_lens_embeddable_factory'; import { serializerMock } from '@kbn/core-saved-objects-base-server-mocks'; diff --git a/x-pack/plugins/cloud_security_posture/common/constants.ts b/x-pack/plugins/cloud_security_posture/common/constants.ts index 5ba3648638e61..587fbdce8cc86 100644 --- a/x-pack/plugins/cloud_security_posture/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/common/constants.ts @@ -5,7 +5,12 @@ * 2.0. */ -import { PostureTypes, VulnSeverity, AwsCredentialsTypeFieldMap } from './types'; +import { + PostureTypes, + VulnSeverity, + AwsCredentialsTypeFieldMap, + GcpCredentialsTypeFieldMap, +} from './types'; export const STATUS_ROUTE_PATH = '/internal/cloud_security_posture/status'; export const STATUS_API_CURRENT_VERSION = '1'; @@ -22,6 +27,7 @@ export const FIND_CSP_RULE_TEMPLATE_ROUTE_PATH = '/internal/cloud_security_postu export const FIND_CSP_RULE_TEMPLATE_API_CURRENT_VERSION = '1'; export const DETECTION_RULE_ALERTS_STATUS_API_CURRENT_VERSION = '1'; +export const DETECTION_RULE_RULES_API_CURRENT_VERSION = '2023-10-31'; export const GET_DETECTION_RULE_ALERTS_STATUS_PATH = '/internal/cloud_security_posture/detection_engine_rules/alerts/_status'; @@ -143,3 +149,8 @@ export const SETUP_ACCESS_CLOUD_SHELL = 'google_cloud_shell'; export const SETUP_ACCESS_MANUAL = 'manual'; export const DETECTION_ENGINE_ALERTS_INDEX_DEFAULT = '.alerts-security.alerts-default'; + +export const GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP: GcpCredentialsTypeFieldMap = { + 'credentials-file': ['gcp.credentials.file'], + 'credentials-json': ['gcp.credentials.json'], +}; diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index 956493de4c573..f2b6c00399915 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -24,6 +24,12 @@ export type AwsCredentialsTypeFieldMap = { [key in AwsCredentialsType]: string[]; }; +export type GcpCredentialsType = 'credentials-file' | 'credentials-json'; + +export type GcpCredentialsTypeFieldMap = { + [key in GcpCredentialsType]: string[]; +}; + export type Evaluation = 'passed' | 'failed' | 'NA'; export type PostureTypes = 'cspm' | 'kspm' | 'vuln_mgmt' | 'all'; diff --git a/x-pack/plugins/cloud_security_posture/common/utils/get_safe_vulnerabilities_query_filter.ts b/x-pack/plugins/cloud_security_posture/common/utils/get_safe_vulnerabilities_query_filter.ts deleted file mode 100644 index 899bc5177458e..0000000000000 --- a/x-pack/plugins/cloud_security_posture/common/utils/get_safe_vulnerabilities_query_filter.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; - -export const getSafeVulnerabilitiesQueryFilter = (query?: QueryDslQueryContainer) => ({ - ...query, - bool: { - ...query?.bool, - filter: [...((query?.bool?.filter as []) || []), { exists: { field: 'resource.id' } }], - }, -}); diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts index 479cc2f62c36a..7e7d25a5b28bd 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.test.ts @@ -185,5 +185,109 @@ describe('test helper methods', () => { shared_credential_file: { value: undefined, type: 'text' }, }); }); + + it('when aws credential type is undefined, return unchanged policy', () => { + const mockPackagePolicy = createPackagePolicyMock(); + mockPackagePolicy.inputs = [ + { + type: 'cloudbeat/cis_eks', + enabled: true, + streams: [ + { + id: 'findings', + enabled: true, + data_stream: { + dataset: 'cloud_security_posture.findings', + type: 'logs', + }, + vars: { + 'aws.credentials.type': { value: undefined }, + access_key_id: { value: 'used', type: 'text' }, + credential_profile_name: { value: 'unused', type: 'text' }, + role_arn: { value: 'unused' }, + secret_access_key: { value: 'used', type: 'text' }, + session_token: { value: 'unused', type: 'text' }, + shared_credential_file: { value: 'unused', type: 'text' }, + }, + }, + ], + }, + ]; + + const cleanedPackage = cleanupCredentials(mockPackagePolicy); + expect(cleanedPackage.inputs[0].streams[0].vars).toEqual({ + 'aws.credentials.type': { value: undefined }, + access_key_id: { value: 'used', type: 'text' }, + credential_profile_name: { value: 'unused', type: 'text' }, + role_arn: { value: 'unused' }, + secret_access_key: { value: 'used', type: 'text' }, + session_token: { value: 'unused', type: 'text' }, + shared_credential_file: { value: 'unused', type: 'text' }, + }); + }); + + it('cleans unused gcp credential methods, when using credentials-file method ', () => { + const mockPackagePolicy = createPackagePolicyMock(); + mockPackagePolicy.inputs = [ + { + type: 'cloudbeat/cis_gcp', + enabled: true, + streams: [ + { + id: 'findings', + enabled: true, + data_stream: { + dataset: 'cloud_security_posture.findings', + type: 'logs', + }, + vars: { + 'gcp.credentials.type': { value: 'credentials-file' }, + 'gcp.credentials.file': { value: 'used' }, + 'gcp.credentials.json': { value: 'unused' }, + }, + }, + ], + }, + ]; + + const cleanedPackage = cleanupCredentials(mockPackagePolicy); + expect(cleanedPackage.inputs[0].streams[0].vars).toEqual({ + 'gcp.credentials.type': { value: 'credentials-file' }, + 'gcp.credentials.file': { value: 'used' }, + 'gcp.credentials.json': { value: undefined }, + }); + }); + + it('when gcp credential type is undefined, return unchanged policy', () => { + const mockPackagePolicy = createPackagePolicyMock(); + mockPackagePolicy.inputs = [ + { + type: 'cloudbeat/cis_gcp', + enabled: true, + streams: [ + { + id: 'findings', + enabled: true, + data_stream: { + dataset: 'cloud_security_posture.findings', + type: 'logs', + }, + vars: { + 'gcp.credentials.type': { value: undefined }, + 'gcp.credentials.file': { value: 'used' }, + 'gcp.credentials.json': { value: 'unused' }, + }, + }, + ], + }, + ]; + + const cleanedPackage = cleanupCredentials(mockPackagePolicy); + expect(cleanedPackage.inputs[0].streams[0].vars).toEqual({ + 'gcp.credentials.type': { value: undefined }, + 'gcp.credentials.file': { value: 'used' }, + 'gcp.credentials.json': { value: 'unused' }, + }); + }); }); }); diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index f50a5ef47bb59..9cf31c944d27a 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -19,8 +19,15 @@ import { CLOUDBEAT_VANILLA, CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP, + GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP, } from '../constants'; -import type { BenchmarkId, Score, BaseCspSetupStatus, AwsCredentialsType } from '../types'; +import type { + BenchmarkId, + Score, + BaseCspSetupStatus, + AwsCredentialsType, + GcpCredentialsType, +} from '../types'; /** * @example @@ -103,12 +110,21 @@ export const getStatusForIndexName = (indexName: string, status?: BaseCspSetupSt export const cleanupCredentials = (packagePolicy: NewPackagePolicy | UpdatePackagePolicy) => { const enabledInput = packagePolicy.inputs.find((i) => i.enabled); - const credentialType: AwsCredentialsType | undefined = + const awsCredentialType: AwsCredentialsType | undefined = enabledInput?.streams?.[0].vars?.['aws.credentials.type']?.value; - - if (credentialType) { - const credsToKeep = AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP[credentialType]; - const credFields = Object.values(AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP).flat(); + const gcpCredentialType: GcpCredentialsType | undefined = + enabledInput?.streams?.[0].vars?.['gcp.credentials.type']?.value; + + if (awsCredentialType || gcpCredentialType) { + let credsToKeep: string[] = [' ']; + let credFields: string[] = [' ']; + if (awsCredentialType) { + credsToKeep = AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP[awsCredentialType]; + credFields = Object.values(AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP).flat(); + } else if (gcpCredentialType) { + credsToKeep = GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP[gcpCredentialType]; + credFields = Object.values(GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP).flat(); + } if (credsToKeep) { // we need to return a copy of the policy with the unused diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/create_detection_rule.ts b/x-pack/plugins/cloud_security_posture/public/common/api/create_detection_rule.ts index a73e75d706e72..88dd8f28104c6 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/create_detection_rule.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/create_detection_rule.ts @@ -5,6 +5,7 @@ * 2.0. */ import { HttpSetup } from '@kbn/core/public'; +import { DETECTION_RULE_RULES_API_CURRENT_VERSION } from '../../../common/constants'; import { RuleCreateProps, RuleResponse } from '../types'; const DETECTION_ENGINE_URL = '/api/detection_engine' as const; @@ -18,6 +19,7 @@ export const createDetectionRule = async ({ rule: RuleCreateProps; }): Promise => { const res = await http.post(DETECTION_ENGINE_RULES_URL, { + version: DETECTION_RULE_RULES_API_CURRENT_VERSION, body: JSON.stringify(rule), }); diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_fetch_detection_rules_by_tags.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_fetch_detection_rules_by_tags.ts index 953b31b1b5428..309698f4219d9 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_fetch_detection_rules_by_tags.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_fetch_detection_rules_by_tags.ts @@ -8,6 +8,7 @@ import { CoreStart } from '@kbn/core/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useQuery } from '@tanstack/react-query'; +import { DETECTION_RULE_RULES_API_CURRENT_VERSION } from '../../../common/constants'; import { RuleResponse } from '../types'; import { DETECTION_ENGINE_RULES_KEY } from '../constants'; @@ -47,6 +48,7 @@ export const useFetchDetectionRulesByTags = (tags: string[]) => { return useQuery([DETECTION_ENGINE_RULES_KEY, tags], () => http.fetch(DETECTION_ENGINE_RULES_URL_FIND, { method: 'GET', + version: DETECTION_RULE_RULES_API_CURRENT_VERSION, query, }) ); diff --git a/x-pack/plugins/cloud_security_posture/public/common/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/constants.ts index 8f51456c009e4..4a5d5bfc7bd9a 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/constants.ts @@ -214,7 +214,7 @@ export const cloudPostureIntegrations: CloudPostureIntegrations = { }, }; export const FINDINGS_DOCS_URL = 'https://ela.st/findings'; -export const MIN_VERSION_GCP_CIS = '1.5.0'; +export const MIN_VERSION_GCP_CIS = '1.5.2'; export const NO_FINDINGS_STATUS_REFRESH_INTERVAL_MS = 10000; diff --git a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_table/use_cloud_posture_table.ts b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_table/use_cloud_posture_table.ts index b26af81cdff43..2d42c2a8303d6 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_table/use_cloud_posture_table.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_table/use_cloud_posture_table.ts @@ -4,12 +4,39 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { useCallback } from 'react'; +import { Dispatch, SetStateAction, useCallback } from 'react'; import { type DataView } from '@kbn/data-views-plugin/common'; +import { BoolQuery } from '@kbn/es-query'; +import { CriteriaWithPagination } from '@elastic/eui'; import { useUrlQuery } from '../use_url_query'; import { usePageSize } from '../use_page_size'; import { getDefaultQuery, useBaseEsQuery, usePersistedQuery } from './utils'; +interface QuerySort { + direction: string; + id: string; +} + +export interface CloudPostureTableResult { + setUrlQuery: (query: any) => void; + // TODO: remove any, this sorting is used for both EuiGrid and EuiTable which uses different types of sorts + sort: any; + filters: any[]; + query?: { bool: BoolQuery }; + queryError?: Error; + pageIndex: number; + // TODO: remove any, urlQuery is an object with query fields but we also add custom fields to it, need to assert usages + urlQuery: any; + setTableOptions: (options: CriteriaWithPagination) => void; + handleUpdateQuery: (query: any) => void; + pageSize: number; + setPageSize: Dispatch>; + onChangeItemsPerPage: (newPageSize: number) => void; + onChangePage: (newPageIndex: number) => void; + onSort: (sort: QuerySort[]) => void; + onResetFilters: () => void; +} + /* Hook for managing common table state and methods for Cloud Posture */ @@ -21,7 +48,7 @@ export const useCloudPostureTable = ({ defaultQuery?: (params: any) => any; dataView: DataView; paginationLocalStorageKey: string; -}) => { +}): CloudPostureTableResult => { const getPersistedDefaultQuery = usePersistedQuery(defaultQuery); const { urlQuery, setUrlQuery } = useUrlQuery(getPersistedDefaultQuery); const { pageSize, setPageSize } = usePageSize(paginationLocalStorageKey); @@ -31,9 +58,10 @@ export const useCloudPostureTable = ({ setPageSize(newPageSize); setUrlQuery({ pageIndex: 0, + pageSize: newPageSize, }); }, - [setUrlQuery, setPageSize] + [setPageSize, setUrlQuery] ); const onResetFilters = useCallback(() => { diff --git a/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx b/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx index 490df0c3d9215..39b37c85aee39 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx @@ -33,8 +33,8 @@ export const AccountsEvaluatedWidget = ({ const cisAwsClusterAmount = filterClustersById(CIS_AWS).length; const cisGcpClusterAmount = filterClustersById(CIS_GCP).length; - const cisAwsBenchmarkName = filterClustersById(CIS_AWS)[0]?.meta.benchmark.name || ''; - const cisGcpBenchmarkName = filterClustersById(CIS_GCP)[0]?.meta.benchmark.name || ''; + const cisAwsBenchmarkName = 'Amazon Web Services (AWS)'; + const cisGcpBenchmarkName = 'Google Cloud Platform (GCP)'; return ( <> diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx index 7fafe17113c84..dc2b46dd364fe 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx @@ -235,7 +235,9 @@ export const AwsCredentialsForm = ({ size="m" options={getSetupFormatOptions()} idSelected={setupFormat} - onChange={onSetupFormatChange} + onChange={(idSelected: SetupFormat) => + idSelected !== setupFormat && onSetupFormatChange(idSelected) + } /> {setupFormat === 'cloud_formation' && ( diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx index 88f6ff77fde21..74685000a98cc 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx @@ -110,56 +110,58 @@ const GoogleCloudShellSetup = () => { ); }; -type GcpFields = Record; +const credentialOptionsList = [ + { + text: i18n.translate('xpack.csp.gcpIntegration.credentialsFileOption', { + defaultMessage: 'Credentials File', + }), + value: 'credentials-file', + }, + { + text: i18n.translate('xpack.csp.gcpIntegration.credentialsJsonOption', { + defaultMessage: 'Credentials JSON', + }), + value: 'credentials-json', + }, +]; + +type GcpFields = Record; interface GcpInputFields { fields: GcpFields; } export const gcpField: GcpInputFields = { fields: { - project_id: { + 'gcp.project_id': { label: i18n.translate('xpack.csp.gcpIntegration.projectidFieldLabel', { defaultMessage: 'Project ID', }), type: 'text', }, - credentials_file: { + 'gcp.credentials.file': { label: i18n.translate('xpack.csp.findings.gcpIntegration.gcpInputText.credentialFileText', { defaultMessage: 'Path to JSON file containing the credentials and key used to subscribe', }), type: 'text', }, - credentials_json: { + 'gcp.credentials.json': { label: i18n.translate('xpack.csp.findings.gcpIntegration.gcpInputText.credentialJSONText', { defaultMessage: 'JSON blob containing the credentials and key used to subscribe', }), type: 'text', }, - credentials_type: { + 'gcp.credentials.type': { label: i18n.translate( 'xpack.csp.findings.gcpIntegration.gcpInputText.credentialSelectBoxTitle', - { defaultMessage: 'Credential' } + { + defaultMessage: 'Credential', + } ), type: 'text', }, }, }; -const credentialOptionsList = [ - { - text: i18n.translate('xpack.csp.gcpIntegration.credentialsFileOption', { - defaultMessage: 'Credentials File', - }), - value: 'credentials-file', - }, - { - text: i18n.translate('xpack.csp.gcpIntegration.credentialsJsonOption', { - defaultMessage: 'Credentials JSON', - }), - value: 'credentials-json', - }, -]; - const getSetupFormatOptions = (): Array<{ id: SetupFormatGCP; label: string; @@ -193,10 +195,7 @@ interface GcpFormProps { onChange: any; } -const getInputVarsFields = ( - input: NewPackagePolicyInput, - fields: GcpInputFields[keyof GcpInputFields] -) => +const getInputVarsFields = (input: NewPackagePolicyInput, fields: GcpFields) => Object.entries(input.streams[0].vars || {}) .filter(([id]) => id in fields) .map(([id, inputVar]) => { @@ -348,7 +347,7 @@ export const GcpCredentialsForm = ({ // Integration is Invalid IF Version is not at least 1.5.0 OR Setup Access is manual but Project ID is empty useEffect(() => { const isProjectIdEmpty = - setupFormat === SETUP_ACCESS_MANUAL && !getFieldById('project_id')?.value; + setupFormat === SETUP_ACCESS_MANUAL && !getFieldById('gcp.project_id')?.value; const isInvalidPolicy = isInvalid || isProjectIdEmpty; setIsValid(!isInvalidPolicy); @@ -411,19 +410,21 @@ const GcpInputVarFields = ({ const getFieldById = (id: keyof GcpInputFields['fields']) => { return fields.find((element) => element.id === id); }; - const projectIdFields = getFieldById('project_id'); - const credentialsTypeFields = getFieldById('credentials_type') || credentialOptionsList[0]; - const credentialFilesFields = getFieldById('credentials_file'); - const credentialJSONFields = getFieldById('credentials_json'); + const projectIdFields = getFieldById('gcp.project_id'); + const credentialsTypeFields = getFieldById('gcp.credentials.type'); + const credentialFilesFields = getFieldById('gcp.credentials.file'); + const credentialJSONFields = getFieldById('gcp.credentials.json'); const credentialFieldValue = credentialOptionsList[0].value; const credentialJSONValue = credentialOptionsList[1].value; + const credentialsTypeValue = credentialsTypeFields?.value || credentialOptionsList[0].value; + return (
    {projectIdFields && ( - + )} - {credentialFilesFields && credentialJSONFields && ( - + {credentialsTypeFields && credentialFilesFields && credentialJSONFields && ( + { - onChange('credentials_type', optionElem.target.value); + onChange(credentialsTypeFields?.id, optionElem.target.value); }} /> )} - - {credentialsTypeFields.value === credentialFieldValue && credentialFilesFields && ( - + {credentialsTypeValue === credentialFieldValue && credentialFilesFields && ( + )} - {credentialsTypeFields?.value === credentialJSONValue && credentialJSONFields && ( - + {credentialsTypeValue === credentialJSONValue && credentialJSONFields && ( + { } as PackageInfo; }; -export const getMockPackageInfoCspmGCP = (packageVersion = '1.5.0') => { +export const getMockPackageInfoCspmGCP = (packageVersion = '1.5.2') => { return { version: packageVersion, name: 'cspm', @@ -130,9 +130,10 @@ const getPolicyMock = ( }; const gcpVarsMock = { - project_id: { type: 'text' }, - credentials_file: { type: 'text' }, - credentials_json: { type: 'text' }, + 'gcp.project_id': { type: 'text' }, + 'gcp.credentials.file': { type: 'text' }, + 'gcp.credentials.json': { type: 'text' }, + 'gcp.credentials.type': { type: 'text' }, }; const dataStream = { type: 'logs', dataset: 'cloud_security_posture.findings' }; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx index 213d03b95266f..c5d4c0e8de3e2 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx @@ -979,7 +979,7 @@ describe('', () => { }); describe('GCP Credentials input fields', () => { - it(`renders ${CLOUDBEAT_GCP} Not supported when version is not at least version 1.5.0`, () => { + it(`renders ${CLOUDBEAT_GCP} Not supported when version is not at least version 1.5.2`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { credentials_type: { value: 'credentials-file' }, @@ -1024,7 +1024,7 @@ describe('', () => { it(`project ID is required for Manual users`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - project_id: { value: undefined }, + 'gcp.project_id': { value: undefined }, setup_access: { value: 'manual' }, }); @@ -1036,7 +1036,7 @@ describe('', () => { updatedPolicy: policy, }); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - project_id: { value: '' }, + 'gcp.project_id': { value: '' }, setup_access: { value: 'manual' }, }); rerender(); @@ -1049,7 +1049,7 @@ describe('', () => { it(`renders ${CLOUDBEAT_GCP} Credentials File fields`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - credentials_type: { value: 'credentials-file' }, + 'gcp.credentials.type': { value: 'credentials-file' }, setup_access: { value: 'manual' }, }); @@ -1067,8 +1067,8 @@ describe('', () => { it(`updates ${CLOUDBEAT_GCP} Credentials File fields`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - project_id: { value: 'a' }, - credentials_type: { value: 'credentials-file' }, + 'gcp.project_id': { value: 'a' }, + 'gcp.credentials.type': { value: 'credentials-file' }, setup_access: { value: 'manual' }, }); @@ -1079,7 +1079,7 @@ describe('', () => { userEvent.type(getByTestId(CIS_GCP_INPUT_FIELDS_TEST_SUBJECTS.CREDENTIALS_FILE), 'b'); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - credentials_file: { value: 'b' }, + 'gcp.credentials.file': { value: 'b' }, }); expect(onChange).toHaveBeenCalledWith({ @@ -1092,7 +1092,7 @@ describe('', () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { setup_access: { value: 'manual' }, - credentials_type: { value: 'credentials-json' }, + 'gcp.credentials.type': { value: 'credentials-json' }, }); const { getByRole, getByLabelText } = render( @@ -1109,8 +1109,8 @@ describe('', () => { it(`updates ${CLOUDBEAT_GCP} Credentials JSON fields`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - project_id: { value: 'a' }, - credentials_type: { value: 'credentials-json' }, + 'gcp.project_id': { value: 'a' }, + 'gcp.credentials.type': { value: 'credentials-json' }, setup_access: { value: 'manual' }, }); @@ -1121,7 +1121,7 @@ describe('', () => { userEvent.type(getByTestId(CIS_GCP_INPUT_FIELDS_TEST_SUBJECTS.CREDENTIALS_JSON), 'b'); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { - credentials_json: { value: 'b' }, + 'gcp.credentials.json': { value: 'b' }, }); expect(onChange).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_detection_rule_counter.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_detection_rule_counter.tsx index 5586f2a20126c..f39379f8c4ddd 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_detection_rule_counter.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_detection_rule_counter.tsx @@ -9,13 +9,19 @@ import type { HttpSetup } from '@kbn/core/public'; import React from 'react'; import { CspFinding } from '../../../../common/schemas/csp_finding'; import { DetectionRuleCounter } from '../../../components/detection_rule_counter'; -import { createDetectionRuleFromFinding } from '../utils/create_detection_rule_from_finding'; +import { + createDetectionRuleFromFinding, + getFindingsDetectionRuleSearchTags, +} from '../utils/create_detection_rule_from_finding'; export const FindingsDetectionRuleCounter = ({ finding }: { finding: CspFinding }) => { const createMisconfigurationRuleFn = async (http: HttpSetup) => await createDetectionRuleFromFinding(http, finding); return ( - + ); }; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_finding.ts b/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_finding.ts index 778c222d2f5e1..a1f8ac3fa5fcc 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_finding.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_finding.ts @@ -50,9 +50,23 @@ const CSP_RULE_TAG_DATA_SOURCE_PREFIX = 'Data Source: '; const STATIC_RULE_TAGS = [CSP_RULE_TAG, CSP_RULE_TAG_USE_CASE]; +/* + * Returns an array of CspFinding tags that can be used to search and filter a detection rule + */ +export const getFindingsDetectionRuleSearchTags = ({ rule }: CspFinding) => { + // ex: cis_gcp to ['CIS', 'GCP'] + const benchmarkIdTags = rule.benchmark.id.split('_').map((tag) => tag.toUpperCase()); + // ex: 'CIS GCP 1.1' + const benchmarkRuleNumberTag = `${rule.benchmark.id.replace('_', ' ').toUpperCase()} ${ + rule.benchmark.rule_number + }`; + + return benchmarkIdTags.concat([benchmarkRuleNumberTag]); +}; + const generateFindingsTags = (finding: CspFinding) => { return [STATIC_RULE_TAGS] - .concat(finding.rule.tags) + .concat(getFindingsDetectionRuleSearchTags(finding)) .concat( finding.rule.benchmark.posture_type ? [ diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx index 31b1efe73b453..a3ae53a25f4d9 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx @@ -17,7 +17,6 @@ import { } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CspVulnerabilityFinding } from '../../../../common/schemas'; import { LATEST_VULNERABILITIES_INDEX_PATTERN } from '../../../../common/constants'; -import { getSafeVulnerabilitiesQueryFilter } from '../../../../common/utils/get_safe_vulnerabilities_query_filter'; import { useKibana } from '../../../common/hooks/use_kibana'; import { showErrorToast } from '../../../common/utils/show_error_toast'; import { FindingsBaseEsQuery } from '../../../common/types'; @@ -37,7 +36,7 @@ interface VulnerabilitiesQuery extends FindingsBaseEsQuery { export const getFindingsQuery = ({ query, sort, pageIndex, pageSize }: VulnerabilitiesQuery) => ({ index: LATEST_VULNERABILITIES_INDEX_PATTERN, - query: getSafeVulnerabilitiesQueryFilter(query), + query, from: pageIndex * pageSize, size: pageSize, sort, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_by_resource.ts b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_by_resource.ts index 706f980408d18..3aa152d427143 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_by_resource.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_by_resource.ts @@ -21,7 +21,6 @@ import { LATEST_VULNERABILITIES_INDEX_PATTERN, VULNERABILITIES_SEVERITY, } from '../../../../common/constants'; -import { getSafeVulnerabilitiesQueryFilter } from '../../../../common/utils/get_safe_vulnerabilities_query_filter'; import { MAX_FINDINGS_TO_LOAD } from '../../../common/constants'; import { useKibana } from '../../../common/hooks/use_kibana'; @@ -60,7 +59,7 @@ export const getQuery = ({ pageSize, }: VulnerabilitiesQuery) => ({ index: LATEST_VULNERABILITIES_INDEX_PATTERN, - query: getSafeVulnerabilitiesQueryFilter(query), + query, aggs: { total: { cardinality: { field: 'resource.id' } }, resources: { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx index 9e241364f6c01..a9b8fdaa2f190 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx @@ -20,7 +20,10 @@ import React, { useCallback, useMemo, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { Routes, Route } from '@kbn/shared-ux-router'; import { LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY } from '../../common/constants'; -import { useCloudPostureTable } from '../../common/hooks/use_cloud_posture_table'; +import { + CloudPostureTableResult, + useCloudPostureTable, +} from '../../common/hooks/use_cloud_posture_table'; import { useLatestVulnerabilities } from './hooks/use_latest_vulnerabilities'; import type { VulnerabilitiesQueryData } from './types'; import { LATEST_VULNERABILITIES_INDEX_PATTERN } from '../../../common/constants'; @@ -63,67 +66,35 @@ const getDefaultQuery = ({ query, filters }: any): any => ({ pageIndex: 0, }); -export const Vulnerabilities = () => { - const { data, isLoading, error } = useFilteredDataView(LATEST_VULNERABILITIES_INDEX_PATTERN); - const getSetupStatus = useCspSetupStatusApi(); - - if (getSetupStatus?.data?.vuln_mgmt?.status !== 'indexed') return ; - - if (error) { - return ; - } - if (isLoading) { - return defaultLoadingRenderer(); - } - - if (!data) { - return defaultNoDataRenderer(); - } - - return ( - - } - /> - } - /> - } - /> - - ); -}; - const VulnerabilitiesDataGrid = ({ dataView, data, isFetching, + onChangeItemsPerPage, + onChangePage, + onSort, + urlQuery, + onResetFilters, + pageSize, + setUrlQuery, + pageIndex, + sort, }: { dataView: DataView; data: VulnerabilitiesQueryData | undefined; isFetching: boolean; -}) => { - const { - pageIndex, - sort, - pageSize, - onChangeItemsPerPage, - onChangePage, - onSort, - urlQuery, - setUrlQuery, - onResetFilters, - } = useCloudPostureTable({ - dataView, - defaultQuery: getDefaultQuery, - paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, - }); +} & Pick< + CloudPostureTableResult, + | 'pageIndex' + | 'sort' + | 'pageSize' + | 'onChangeItemsPerPage' + | 'onChangePage' + | 'onSort' + | 'urlQuery' + | 'setUrlQuery' + | 'onResetFilters' +>) => { const { euiTheme } = useEuiTheme(); const styles = useStyles(); const [showHighlight, setHighlight] = useState(false); @@ -131,7 +102,9 @@ const VulnerabilitiesDataGrid = ({ const invalidIndex = -1; const selectedVulnerability = useMemo(() => { - return data?.page[urlQuery.vulnerabilityIndex]; + if (urlQuery.vulnerabilityIndex !== undefined) { + return data?.page[urlQuery.vulnerabilityIndex]; + } }, [data?.page, urlQuery.vulnerabilityIndex]); const onCloseFlyout = () => { @@ -192,7 +165,9 @@ const VulnerabilitiesDataGrid = ({ const flyoutVulnerabilityIndex = urlQuery?.vulnerabilityIndex; - const selectedVulnerabilityIndex = flyoutVulnerabilityIndex + pageIndex * pageSize; + const selectedVulnerabilityIndex = flyoutVulnerabilityIndex + ? flyoutVulnerabilityIndex + pageIndex * pageSize + : undefined; const renderCellValue = useMemo(() => { const Cell: React.FC = ({ @@ -390,8 +365,21 @@ const VulnerabilitiesDataGrid = ({ ); }; + const VulnerabilitiesContent = ({ dataView }: { dataView: DataView }) => { - const { pageIndex, query, sort, queryError, pageSize, setUrlQuery } = useCloudPostureTable({ + const { + sort, + query, + queryError, + pageSize, + pageIndex, + onChangeItemsPerPage, + onChangePage, + onSort, + urlQuery, + setUrlQuery, + onResetFilters, + } = useCloudPostureTable({ dataView, defaultQuery: getDefaultQuery, paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, @@ -443,8 +431,58 @@ const VulnerabilitiesContent = ({ dataView }: { dataView: DataView }) => { {error && } {!error && ( - + )} ); }; + +export const Vulnerabilities = () => { + const { data, isLoading, error } = useFilteredDataView(LATEST_VULNERABILITIES_INDEX_PATTERN); + const getSetupStatus = useCspSetupStatusApi(); + + if (getSetupStatus?.data?.vuln_mgmt?.status !== 'indexed') return ; + + if (error) { + return ; + } + if (isLoading) { + return defaultLoadingRenderer(); + } + + if (!data) { + return defaultNoDataRenderer(); + } + + return ( + + } + /> + } + /> + } + /> + + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/resource_vulnerabilities/resource_vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/resource_vulnerabilities/resource_vulnerabilities.tsx index 2f1389015e907..673dd2e8130e4 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/resource_vulnerabilities/resource_vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/resource_vulnerabilities/resource_vulnerabilities.tsx @@ -21,7 +21,10 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { Link, useParams, generatePath } from 'react-router-dom'; import type { BoolQuery } from '@kbn/es-query'; import { LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY } from '../../../../common/constants'; -import { useCloudPostureTable } from '../../../../common/hooks/use_cloud_posture_table'; +import { + CloudPostureTableResult, + useCloudPostureTable, +} from '../../../../common/hooks/use_cloud_posture_table'; import { useLatestVulnerabilities } from '../../hooks/use_latest_vulnerabilities'; import type { VulnerabilitiesQueryData } from '../../types'; import { ErrorCallout } from '../../../configurations/layout/error_callout'; @@ -68,26 +71,31 @@ const ResourceVulnerabilitiesDataGrid = ({ dataView, data, isFetching, + pageIndex, + sort, + pageSize, + onChangeItemsPerPage, + onChangePage, + onSort, + urlQuery, + setUrlQuery, + onResetFilters, }: { dataView: DataView; data: VulnerabilitiesQueryData; isFetching: boolean; -}) => { - const { - pageIndex, - sort, - pageSize, - onChangeItemsPerPage, - onChangePage, - onSort, - urlQuery, - setUrlQuery, - onResetFilters, - } = useCloudPostureTable({ - dataView, - defaultQuery: getDefaultQuery, - paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, - }); +} & Pick< + CloudPostureTableResult, + | 'pageIndex' + | 'sort' + | 'pageSize' + | 'onChangeItemsPerPage' + | 'onChangePage' + | 'onSort' + | 'urlQuery' + | 'setUrlQuery' + | 'onResetFilters' +>) => { const { euiTheme } = useEuiTheme(); const styles = useStyles(); @@ -355,7 +363,19 @@ export const ResourceVulnerabilities = ({ dataView }: { dataView: DataView }) => const params = useParams<{ resourceId: string }>(); const resourceId = decodeURIComponent(params.resourceId); - const { pageIndex, query, sort, queryError, pageSize, setUrlQuery } = useCloudPostureTable({ + const { + pageIndex, + pageSize, + onChangeItemsPerPage, + onChangePage, + query, + sort, + onSort, + queryError, + urlQuery, + setUrlQuery, + onResetFilters, + } = useCloudPostureTable({ dataView, defaultQuery: getDefaultQuery, paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, @@ -457,7 +477,20 @@ export const ResourceVulnerabilities = ({ dataView }: { dataView: DataView }) => {error && } {!error && ( - + )} ); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/vulnerabilities_by_resource.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/vulnerabilities_by_resource.tsx index caa5cca3a3ac1..89488bf52046b 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/vulnerabilities_by_resource.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/vulnerabilities_by_resource.tsx @@ -19,7 +19,10 @@ import { i18n } from '@kbn/i18n'; import { Link, generatePath } from 'react-router-dom'; import { LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY } from '../../../common/constants'; import { findingsNavigation } from '../../../common/navigation/constants'; -import { useCloudPostureTable } from '../../../common/hooks/use_cloud_posture_table'; +import { + CloudPostureTableResult, + useCloudPostureTable, +} from '../../../common/hooks/use_cloud_posture_table'; import { ErrorCallout } from '../../configurations/layout/error_callout'; import { FindingsSearchBar } from '../../configurations/layout/findings_search_bar'; import { useLimitProperties } from '../../../common/utils/get_limit_properties'; @@ -54,26 +57,31 @@ const VulnerabilitiesByResourceDataGrid = ({ dataView, data, isFetching, + pageIndex, + sort, + pageSize, + onChangeItemsPerPage, + onChangePage, + onSort, + urlQuery, + setUrlQuery, + onResetFilters, }: { dataView: DataView; data: VulnerabilitiesByResourceQueryData | undefined; isFetching: boolean; -}) => { - const { - pageIndex, - sort, - pageSize, - onChangeItemsPerPage, - onChangePage, - onSort, - urlQuery, - setUrlQuery, - onResetFilters, - } = useCloudPostureTable({ - dataView, - defaultQuery: getDefaultQuery, - paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, - }); +} & Pick< + CloudPostureTableResult, + | 'pageIndex' + | 'sort' + | 'pageSize' + | 'onChangeItemsPerPage' + | 'onChangePage' + | 'onSort' + | 'urlQuery' + | 'setUrlQuery' + | 'onResetFilters' +>) => { const styles = useStyles(); const { isLastLimitedPage, limitedTotalItemCount } = useLimitProperties({ @@ -232,7 +240,19 @@ const VulnerabilitiesByResourceDataGrid = ({ }; export const VulnerabilitiesByResource = ({ dataView }: { dataView: DataView }) => { - const { pageIndex, query, sort, queryError, pageSize, setUrlQuery } = useCloudPostureTable({ + const { + pageIndex, + onChangeItemsPerPage, + onChangePage, + pageSize, + query, + sort, + onSort, + queryError, + urlQuery, + setUrlQuery, + onResetFilters, + } = useCloudPostureTable({ dataView, defaultQuery: getDefaultQuery, paginationLocalStorageKey: LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY, @@ -273,6 +293,15 @@ export const VulnerabilitiesByResource = ({ dataView }: { dataView: DataView }) dataView={dataView} data={data} isFetching={isFetching} + pageIndex={pageIndex} + sort={sort} + pageSize={pageSize} + onChangeItemsPerPage={onChangeItemsPerPage} + onChangePage={onChangePage} + onSort={onSort} + urlQuery={urlQuery} + setUrlQuery={setUrlQuery} + onResetFilters={onResetFilters} /> )} diff --git a/x-pack/plugins/cloud_security_posture/server/config.ts b/x-pack/plugins/cloud_security_posture/server/config.ts index 472f66c78be8c..735cdb3cbe00f 100644 --- a/x-pack/plugins/cloud_security_posture/server/config.ts +++ b/x-pack/plugins/cloud_security_posture/server/config.ts @@ -4,14 +4,23 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import { schema, type TypeOf } from '@kbn/config-schema'; import type { PluginConfigDescriptor } from '@kbn/core/server'; +import { schema, offeringBasedSchema, type TypeOf } from '@kbn/config-schema'; + const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), + + // Setting only allowed in the Serverless offering + serverless: schema.object({ + enabled: offeringBasedSchema({ + serverless: schema.literal(true), + options: { defaultValue: schema.contextRef('serverless') }, + }), + }), }); -type CloudSecurityPostureConfig = TypeOf; + +export type CloudSecurityPostureConfig = TypeOf; export const config: PluginConfigDescriptor = { schema: configSchema, diff --git a/x-pack/plugins/cloud_security_posture/server/create_indices/create_indices.ts b/x-pack/plugins/cloud_security_posture/server/create_indices/create_indices.ts index c269e201f4243..06e13248fa1c5 100644 --- a/x-pack/plugins/cloud_security_posture/server/create_indices/create_indices.ts +++ b/x-pack/plugins/cloud_security_posture/server/create_indices/create_indices.ts @@ -4,10 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import { errors } from '@elastic/elasticsearch'; import type { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/types'; - +import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import { BENCHMARK_SCORE_INDEX_DEFAULT_NS, BENCHMARK_SCORE_INDEX_PATTERN, @@ -20,8 +19,21 @@ import { latestFindingsPipelineIngestConfig, scorePipelineIngestConfig } from '. import { latestIndexConfigs } from './latest_indices'; import { IndexConfig, IndexTemplateParams } from './types'; +import { CloudSecurityPostureConfig } from '../config'; + +interface IndexTemplateSettings { + index: { + default_pipeline: string; + }; + lifecycle?: { name: string }; +} + // TODO: Add integration tests -export const initializeCspIndices = async (esClient: ElasticsearchClient, logger: Logger) => { +export const initializeCspIndices = async ( + esClient: ElasticsearchClient, + cloudSecurityPostureConfig: CloudSecurityPostureConfig, + logger: Logger +) => { await Promise.allSettled([ createPipelineIfNotExists(esClient, scorePipelineIngestConfig, logger), createPipelineIfNotExists(esClient, latestFindingsPipelineIngestConfig, logger), @@ -32,9 +44,14 @@ export const initializeCspIndices = async (esClient: ElasticsearchClient, logger createVulnerabilitiesLatestIndexPromise, createBenchmarkScoreIndexPromise, ] = await Promise.allSettled([ - createLatestIndex(esClient, logger, latestIndexConfigs.findings), - createLatestIndex(esClient, logger, latestIndexConfigs.vulnerabilities), - createBenchmarkScoreIndex(esClient, logger), + createLatestIndex(esClient, latestIndexConfigs.findings, cloudSecurityPostureConfig, logger), + createLatestIndex( + esClient, + latestIndexConfigs.vulnerabilities, + cloudSecurityPostureConfig, + logger + ), + createBenchmarkScoreIndex(esClient, cloudSecurityPostureConfig, logger), ]); if (createFindingsLatestIndexPromise.status === 'rejected') { @@ -48,25 +65,31 @@ export const initializeCspIndices = async (esClient: ElasticsearchClient, logger } }; -const createBenchmarkScoreIndex = async (esClient: ElasticsearchClient, logger: Logger) => { +const createBenchmarkScoreIndex = async ( + esClient: ElasticsearchClient, + cloudSecurityPostureConfig: CloudSecurityPostureConfig, + logger: Logger +) => { try { // Deletes old assets from previous versions as part of upgrade process const INDEX_TEMPLATE_V830 = 'cloud_security_posture.scores'; await deleteIndexTemplateSafe(esClient, logger, INDEX_TEMPLATE_V830); + const settings: IndexTemplateSettings = { + index: { + default_pipeline: latestFindingsPipelineIngestConfig.id, + }, + lifecycle: { name: '' }, + }; + if (cloudSecurityPostureConfig.serverless.enabled) delete settings.lifecycle; + // We always want to keep the index template updated await esClient.indices.putIndexTemplate({ name: BENCHMARK_SCORE_INDEX_TEMPLATE_NAME, index_patterns: BENCHMARK_SCORE_INDEX_PATTERN, template: { mappings: benchmarkScoreMapping, - settings: { - default_pipeline: scorePipelineIngestConfig.id, - // TODO: once we will convert the score index to datastream we will no longer override the ilm to be empty - lifecycle: { - name: '', - }, - }, + settings, }, _meta: { package: { @@ -98,8 +121,9 @@ const createBenchmarkScoreIndex = async (esClient: ElasticsearchClient, logger: const createLatestIndex = async ( esClient: ElasticsearchClient, - logger: Logger, - indexConfig: IndexConfig + indexConfig: IndexConfig, + cloudSecurityPostureConfig: CloudSecurityPostureConfig, + logger: Logger ) => { const { indexName, indexPattern, indexTemplateName, indexDefaultName } = indexConfig; try { @@ -121,7 +145,7 @@ const createLatestIndex = async ( }; // We always want to keep the index template updated - await updateIndexTemplate(esClient, logger, indexTemplateParams); + await updateIndexTemplate(esClient, indexTemplateParams, cloudSecurityPostureConfig, logger); const result = await createIndexSafe(esClient, logger, indexDefaultName); @@ -192,10 +216,21 @@ const createIndexSafe = async (esClient: ElasticsearchClient, logger: Logger, in const updateIndexTemplate = async ( esClient: ElasticsearchClient, - logger: Logger, - indexTemplateParams: IndexTemplateParams + indexTemplateParams: IndexTemplateParams, + cloudSecurityPostureConfig: CloudSecurityPostureConfig, + logger: Logger ) => { const { indexTemplateName, indexPattern, template, composedOf, _meta } = indexTemplateParams; + + const settings: IndexTemplateSettings = { + ...template?.settings, // nothing inside + index: { + default_pipeline: latestFindingsPipelineIngestConfig.id, + }, + lifecycle: { name: '' }, + }; + if (cloudSecurityPostureConfig.serverless.enabled) delete settings.lifecycle; + try { await esClient.indices.putIndexTemplate({ name: indexTemplateName, @@ -203,18 +238,13 @@ const updateIndexTemplate = async ( priority: 500, template: { mappings: template?.mappings, - settings: { - ...template?.settings, - default_pipeline: latestFindingsPipelineIngestConfig.id, - lifecycle: { - name: '', - }, - }, + settings, aliases: template?.aliases, }, _meta, composed_of: composedOf, }); + logger.info(`Updated index template successfully [Name: ${indexTemplateName}]`); } catch (e) { logger.error(`Failed to update index template [Name: ${indexTemplateName}]`); diff --git a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/alert_stats_collector.ts b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/alert_stats_collector.ts index 7e63af4fb1320..1edd6ca731c3e 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/alert_stats_collector.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/alert_stats_collector.ts @@ -9,53 +9,28 @@ import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import type { CloudSecurityAlertsStats } from './types'; import { DETECTION_ENGINE_ALERTS_INDEX_DEFAULT } from '../../../../common/constants'; -interface AlertsStats { - aggregations: { - cspm: { - rules_count: { - value: number; - }; - alerts_open: { - doc_count: number; - }; - alerts_acknowledged: { - doc_count: number; - }; - alerts_closed: { - doc_count: number; - }; - }; - kspm: { - rules_count: { - value: number; - }; - alerts_open: { - doc_count: number; - }; - alerts_acknowledged: { - doc_count: number; - }; - alerts_closed: { - doc_count: number; - }; - }; - vuln_mgmt: { - rules_count: { - value: number; - }; - alerts_open: { - doc_count: number; - }; - alerts_acknowledged: { - doc_count: number; - }; - alerts_closed: { - doc_count: number; - }; - }; +interface AlertStat { + doc_count: number; + rules_count: { + value: number; + }; + alerts_open: { + doc_count: number; + }; + alerts_acknowledged: { + doc_count: number; + }; + alerts_closed: { + doc_count: number; }; } +interface AlertsStats { + cspm: AlertStat; + kspm: AlertStat; + vuln_mgmt: AlertStat; +} + const getAlertsStatsQuery = (index: string) => ({ size: 0, query: { @@ -187,20 +162,25 @@ export const getAlertsStats = async ( if (isIndexExists) { const alertsStats = await esClient.search(getAlertsStatsQuery(index)); - const postureTypes = ['cspm', 'kspm', 'vuln_mgmt'] as const; - return postureTypes.map((postureType) => ({ - posture_type: postureType, - rules_count: alertsStats.aggregations?.aggregations[postureType].rules_count.value, - alerts_count: alertsStats.aggregations?.aggregations[postureType].alerts_open.doc_count, - alerts_open_count: - alertsStats.aggregations?.aggregations[postureType].alerts_open.doc_count, - alerts_acknowledged_count: - alertsStats.aggregations?.aggregations[postureType].alerts_acknowledged.doc_count, - alerts_closed_count: - alertsStats.aggregations?.aggregations[postureType].alerts_closed.doc_count, - })) as CloudSecurityAlertsStats[]; + return postureTypes + .filter( + (postureType) => + alertsStats?.aggregations?.[postureType]?.doc_count && + alertsStats.aggregations[postureType].doc_count > 0 + ) + .map((postureType): CloudSecurityAlertsStats => { + const postureTypeData = alertsStats!.aggregations![postureType]; + return { + posture_type: postureType, + rules_count: postureTypeData.rules_count?.value, + alerts_count: postureTypeData.doc_count, + alerts_open_count: postureTypeData.alerts_open?.doc_count, + alerts_acknowledged_count: postureTypeData.alerts_acknowledged?.doc_count, + alerts_closed_count: postureTypeData.alerts_closed?.doc_count, + }; + }); } return []; } catch (e) { diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index 30ff887a354ca..8b77581efd39d 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -49,6 +49,7 @@ import { setupFindingsStatsTask, } from './tasks/findings_stats_task'; import { registerCspmUsageCollector } from './lib/telemetry/collectors/register'; +import { CloudSecurityPostureConfig } from './config'; export class CspPlugin implements @@ -60,6 +61,7 @@ export class CspPlugin > { private readonly logger: Logger; + private readonly config: CloudSecurityPostureConfig; private isCloudEnabled?: boolean; /** @@ -69,8 +71,9 @@ export class CspPlugin */ #isInitialized: boolean = false; - constructor(initializerContext: PluginInitializerContext) { + constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); + this.config = initializerContext.config.get(); } public setup( @@ -203,7 +206,7 @@ export class CspPlugin async initialize(core: CoreStart, taskManager: TaskManagerStartContract): Promise { this.logger.debug('initialize'); const esClient = core.elasticsearch.client.asInternalUser; - await initializeCspIndices(esClient, this.logger); + await initializeCspIndices(esClient, this.config, this.logger); await initializeCspTransforms(esClient, this.logger); await scheduleFindingsStatsTask(taskManager, this.logger); this.#isInitialized = true; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts index 9863b865c7542..6eec795e2dad6 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { AggFieldBucket, PatchableVulnerabilityStat } from '../../../common/types'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS } from '../../../common/constants'; @@ -26,9 +26,19 @@ export interface PatchableVulnerabilitiesQueryResult { }; } -const getPatchableVulnerabilitiesQuery = (query: QueryDslQueryContainer): SearchRequest => ({ +const getPatchableVulnerabilitiesQuery = (): SearchRequest => ({ size: 0, - query, + query: { + bool: { + filter: [ + { + exists: { + field: 'package.fixed_version', + }, + }, + ], + }, + }, index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, aggs: { patchable_vulnerabilities: { @@ -64,24 +74,10 @@ const getPatchableVulnerabilitiesQuery = (query: QueryDslQueryContainer): Search }); export const getTopPatchableVulnerabilities = async ( - esClient: ElasticsearchClient, - query: QueryDslQueryContainer + esClient: ElasticsearchClient ): Promise => { const queryResult = await esClient.search( - getPatchableVulnerabilitiesQuery({ - ...query, - bool: { - ...query.bool, - filter: [ - ...(query.bool?.filter as QueryDslQueryContainer[]), - { - exists: { - field: 'package.fixed_version', - }, - }, - ], - }, - }) + getPatchableVulnerabilitiesQuery() ); if (!queryResult?.aggregations?.patchable_vulnerabilities) return []; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts index 962b4135ad96f..cd8c5b64f532d 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { VulnerabilityStat } from '../../../common/types'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS } from '../../../common/constants'; @@ -72,9 +72,11 @@ export interface VulnerabilitiesQueryResult { }; } -const getVulnerabilitiesQuery = (query: QueryDslQueryContainer): SearchRequest => ({ +const getVulnerabilitiesQuery = (): SearchRequest => ({ size: 0, - query, + query: { + match_all: {}, + }, index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, aggs: { vulnerabilities: { @@ -126,11 +128,10 @@ const getVulnerabilitiesQuery = (query: QueryDslQueryContainer): SearchRequest = }); export const getTopVulnerabilities = async ( - esClient: ElasticsearchClient, - query: QueryDslQueryContainer + esClient: ElasticsearchClient ): Promise => { const queryResult = await esClient.search( - getVulnerabilitiesQuery(query) + getVulnerabilitiesQuery() ); if (!queryResult?.aggregations?.vulnerabilities) return []; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts index 1753e3499fee3..0a41a11aeedea 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { AggFieldBucket, VulnerableResourceStat } from '../../../common/types'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS } from '../../../common/constants'; @@ -23,9 +23,11 @@ export interface VulnerableResourcesQueryResult { }; } -const getVulnerabilitiesResourcesQuery = (query: QueryDslQueryContainer): SearchRequest => ({ +const getVulnerabilitiesResourcesQuery = (): SearchRequest => ({ size: 0, - query, + query: { + match_all: {}, + }, index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, aggs: { vulnerable_resources: { @@ -55,11 +57,10 @@ const getVulnerabilitiesResourcesQuery = (query: QueryDslQueryContainer): Search }); export const getTopVulnerableResources = async ( - esClient: ElasticsearchClient, - query: QueryDslQueryContainer + esClient: ElasticsearchClient ): Promise => { const queryResult = await esClient.search( - getVulnerabilitiesResourcesQuery(query) + getVulnerabilitiesResourcesQuery() ); if (!queryResult?.aggregations?.vulnerable_resources) return []; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_statistics.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_statistics.ts index 5139e3cb92ba9..8458d66817f82 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_statistics.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_statistics.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, @@ -30,11 +30,11 @@ export interface VulnerabilitiesStatisticsQueryResult { }; } -export const getVulnerabilitiesStatisticsQuery = ( - query: QueryDslQueryContainer -): SearchRequest => ({ +export const getVulnerabilitiesStatisticsQuery = (): SearchRequest => ({ size: 0, - query, + query: { + match_all: {}, + }, index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, aggs: { critical: { @@ -59,12 +59,9 @@ export const getVulnerabilitiesStatisticsQuery = ( }, }); -export const getVulnerabilitiesStatistics = async ( - esClient: ElasticsearchClient, - query: QueryDslQueryContainer -) => { +export const getVulnerabilitiesStatistics = async (esClient: ElasticsearchClient) => { const queryResult = await esClient.search( - getVulnerabilitiesStatisticsQuery(query) + getVulnerabilitiesStatisticsQuery() ); return { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts index be45fefeccd3d..e77851062217c 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts @@ -9,18 +9,12 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { getVulnerabilitiesTrends } from './get_vulnerabilities_trend'; import type { CnvmDashboardData } from '../../../common/types'; import { VULNERABILITIES_DASHBOARD_ROUTE_PATH } from '../../../common/constants'; -import { getSafeVulnerabilitiesQueryFilter } from '../../../common/utils/get_safe_vulnerabilities_query_filter'; import { CspRouter } from '../../types'; import { getVulnerabilitiesStatistics } from './get_vulnerabilities_statistics'; import { getTopVulnerableResources } from './get_top_vulnerable_resources'; import { getTopPatchableVulnerabilities } from './get_top_patchable_vulnerabilities'; import { getTopVulnerabilities } from './get_top_vulnerabilities'; -export interface KeyDocCount { - key: TKey; - doc_count: number; -} - export const defineGetVulnerabilitiesDashboardRoute = (router: CspRouter): void => router.get( { @@ -36,8 +30,6 @@ export const defineGetVulnerabilitiesDashboardRoute = (router: CspRouter): void try { const esClient = cspContext.esClient.asCurrentUser; - const query = getSafeVulnerabilitiesQueryFilter(); - const [ cnvmStatistics, vulnTrends, @@ -45,11 +37,11 @@ export const defineGetVulnerabilitiesDashboardRoute = (router: CspRouter): void topPatchableVulnerabilities, topVulnerabilities, ] = await Promise.all([ - getVulnerabilitiesStatistics(esClient, query), + getVulnerabilitiesStatistics(esClient), getVulnerabilitiesTrends(esClient), - getTopVulnerableResources(esClient, query), - getTopPatchableVulnerabilities(esClient, query), - getTopVulnerabilities(esClient, query), + getTopVulnerableResources(esClient), + getTopPatchableVulnerabilities(esClient), + getTopVulnerabilities(esClient), ]); const body: CnvmDashboardData = { diff --git a/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts b/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts index bec5aacd9f95c..f40ce3f7dc4ab 100644 --- a/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts +++ b/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts @@ -14,7 +14,6 @@ import { import { SearchRequest } from '@kbn/data-plugin/common'; import { ElasticsearchClient } from '@kbn/core/server'; import type { Logger } from '@kbn/core/server'; -import { getSafeVulnerabilitiesQueryFilter } from '../../common/utils/get_safe_vulnerabilities_query_filter'; import { getSafePostureTypeRuntimeMapping } from '../../common/runtime_mappings/get_safe_posture_type_runtime_mapping'; import { getIdentifierRuntimeMapping } from '../../common/runtime_mappings/get_identifier_runtime_mapping'; import { FindingsStatsTaskResult, ScoreByPolicyTemplateBucket, VulnSeverityAggs } from './types'; @@ -186,7 +185,9 @@ const getScoreQuery = (): SearchRequest => ({ const getVulnStatsTrendQuery = (): SearchRequest => ({ index: LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, size: 0, - query: getSafeVulnerabilitiesQueryFilter(), + query: { + match_all: {}, + }, aggs: { critical: { filter: { term: { 'vulnerability.severity': VULNERABILITIES_SEVERITY.CRITICAL } }, diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.tsx index d4b5bf3f57e27..90a17f070e1f7 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.tsx @@ -9,7 +9,7 @@ import React, { FC } from 'react'; import { EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FieldIcon } from '@kbn/react-field'; -import { getFieldTypeName } from '@kbn/unified-field-list/src/utils/field_types/get_field_type_name'; +import { getFieldTypeName } from '@kbn/discover-utils'; import './_index.scss'; interface FieldTypeIconProps { diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_types_filter/field_types_filter.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/field_types_filter/field_types_filter.tsx index 401a437eb0f67..b4a09b3cb1c9d 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_types_filter/field_types_filter.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_types_filter/field_types_filter.tsx @@ -8,7 +8,7 @@ import React, { FC, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { getFieldTypeName } from '@kbn/unified-field-list/src/utils/field_types/get_field_type_name'; +import { getFieldTypeName } from '@kbn/discover-utils'; import { FieldTypesHelpPopover } from './field_types_help_popover'; import { MultiSelectPicker, Option } from '../multi_select_picker'; import type { diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx index 517400024084a..46adbecdfc814 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/field_type_filter.tsx @@ -9,7 +9,7 @@ import React, { FC, useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; -import { getFieldTypeName } from '@kbn/unified-field-list/src/utils/field_types/get_field_type_name'; +import { getFieldTypeName } from '@kbn/discover-utils'; import { useCurrentEuiTheme } from '../../../common/hooks/use_current_eui_theme'; import { FieldTypesHelpPopover } from '../../../common/components/field_types_filter/field_types_help_popover'; import { FieldTypeIcon } from '../../../common/components/field_type_icon'; diff --git a/x-pack/plugins/data_visualizer/tsconfig.json b/x-pack/plugins/data_visualizer/tsconfig.json index 75dd55b83e274..5221ef48b5efc 100644 --- a/x-pack/plugins/data_visualizer/tsconfig.json +++ b/x-pack/plugins/data_visualizer/tsconfig.json @@ -26,6 +26,7 @@ "@kbn/data-views-plugin", "@kbn/datemath", "@kbn/discover-plugin", + "@kbn/discover-utils", "@kbn/embeddable-plugin", "@kbn/embeddable-plugin", "@kbn/es-query", diff --git a/x-pack/plugins/discover_log_explorer/README.md b/x-pack/plugins/discover_log_explorer/README.md deleted file mode 100755 index 4b3453a451bf8..0000000000000 --- a/x-pack/plugins/discover_log_explorer/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Discover Log Explorer - -This plugin registers a `log-explorer` profile using the Discover customization framework, offering several affordances specifically designed for log consumption. - -The plugin enhances the capabilities of Discover in the following ways: - -- **Dataset selector**: this customization on the Discover page replaces the DataViews picker with a Logs dataset selector built ad-hoc to provide a better experience when navigating throught all the available datasets. - diff --git a/x-pack/plugins/discover_log_explorer/common/runtime_types.ts b/x-pack/plugins/discover_log_explorer/common/runtime_types.ts deleted file mode 100644 index d6d0336eafdd7..0000000000000 --- a/x-pack/plugins/discover_log_explorer/common/runtime_types.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { fold } from 'fp-ts/lib/Either'; -import { identity } from 'fp-ts/lib/function'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { Context, Errors, IntersectionType, Type, UnionType, ValidationError } from 'io-ts'; - -type ErrorFactory = (message: string) => Error; - -const getErrorPath = ([first, ...rest]: Context): string[] => { - if (typeof first === 'undefined') { - return []; - } else if (first.type instanceof IntersectionType) { - const [, ...next] = rest; - return getErrorPath(next); - } else if (first.type instanceof UnionType) { - const [, ...next] = rest; - return [first.key, ...getErrorPath(next)]; - } - - return [first.key, ...getErrorPath(rest)]; -}; - -const getErrorType = ({ context }: ValidationError) => - context[context.length - 1]?.type?.name ?? 'unknown'; - -const formatError = (error: ValidationError) => - error.message ?? - `in ${getErrorPath(error.context).join('/')}: ${JSON.stringify( - error.value - )} does not match expected type ${getErrorType(error)}`; - -export const formatErrors = (errors: ValidationError[]) => - `Failed to validate: \n${errors.map((error) => ` ${formatError(error)}`).join('\n')}`; - -export const createPlainError = (message: string) => new Error(message); - -export const throwErrors = (createError: ErrorFactory) => (errors: Errors) => { - throw createError(formatErrors(errors)); -}; - -export const decodeOrThrow = - ( - runtimeType: Type, - createError: ErrorFactory = createPlainError - ) => - (inputValue: InputValue) => - pipe(runtimeType.decode(inputValue), fold(throwErrors(createError), identity)); diff --git a/x-pack/plugins/discover_log_explorer/kibana.jsonc b/x-pack/plugins/discover_log_explorer/kibana.jsonc deleted file mode 100644 index 89d00e3ce4eeb..0000000000000 --- a/x-pack/plugins/discover_log_explorer/kibana.jsonc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "plugin", - "id": "@kbn/discover-log-explorer-plugin", - "owner": "@elastic/infra-monitoring-ui", - "description": "This plugin exposes and registers Logs+ features.", - "plugin": { - "id": "discoverLogExplorer", - "server": true, - "browser": true, - "configPath": ["xpack", "discoverLogExplorer"], - "requiredPlugins": ["data", "dataViews", "discover", "fleet", "kibanaReact", "kibanaUtils", "controls", "embeddable"], - "optionalPlugins": [], - "requiredBundles": [] - } -} diff --git a/x-pack/plugins/discover_log_explorer/public/deep_links.ts b/x-pack/plugins/discover_log_explorer/public/deep_links.ts deleted file mode 100644 index 2740fbab56b16..0000000000000 --- a/x-pack/plugins/discover_log_explorer/public/deep_links.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { AppDeepLink, AppNavLinkStatus, DEFAULT_APP_CATEGORIES } from '@kbn/core/public'; -import { i18n } from '@kbn/i18n'; -import { LOG_EXPLORER_PROFILE_ID } from '../common/constants'; - -export const getLogExplorerDeepLink = ({ isVisible }: { isVisible: boolean }): AppDeepLink => ({ - id: LOG_EXPLORER_PROFILE_ID, - title: i18n.translate('xpack.discoverLogExplorer.deepLink', { - defaultMessage: 'Logs Explorer', - }), - path: `#/p/${LOG_EXPLORER_PROFILE_ID}`, - category: DEFAULT_APP_CATEGORIES.observability, - euiIconType: 'logoObservability', - navLinkStatus: isVisible ? AppNavLinkStatus.visible : AppNavLinkStatus.default, -}); diff --git a/x-pack/plugins/discover_log_explorer/public/plugin.ts b/x-pack/plugins/discover_log_explorer/public/plugin.ts deleted file mode 100644 index e39c831cdb432..0000000000000 --- a/x-pack/plugins/discover_log_explorer/public/plugin.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; -import { LOG_EXPLORER_PROFILE_ID } from '../common/constants'; -import { DiscoverLogExplorerConfig } from '../common/plugin_config'; -import { createLogExplorerProfileCustomizations } from './customizations/log_explorer_profile'; -import { getLogExplorerDeepLink } from './deep_links'; -import { - DiscoverLogExplorerPluginSetup, - DiscoverLogExplorerPluginStart, - DiscoverLogExplorerStartDeps, -} from './types'; - -export class DiscoverLogExplorerPlugin - implements Plugin -{ - private config: DiscoverLogExplorerConfig; - - constructor(context: PluginInitializerContext) { - this.config = context.config.get(); - } - - public setup() {} - - public start(core: CoreStart, plugins: DiscoverLogExplorerStartDeps) { - const { discover, data } = plugins; - - discover.registerCustomizationProfile(LOG_EXPLORER_PROFILE_ID, { - customize: createLogExplorerProfileCustomizations({ core, data }), - deepLinks: [getLogExplorerDeepLink({ isVisible: this.config.featureFlags.deepLinkVisible })], - }); - } -} diff --git a/x-pack/plugins/discover_log_explorer/public/types.ts b/x-pack/plugins/discover_log_explorer/public/types.ts deleted file mode 100644 index 4ec95ba94ec5a..0000000000000 --- a/x-pack/plugins/discover_log_explorer/public/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. - */ -import { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { DiscoverStart } from '@kbn/discover-plugin/public'; - -export type DiscoverLogExplorerPluginSetup = void; -export type DiscoverLogExplorerPluginStart = void; - -export interface DiscoverLogExplorerStartDeps { - data: DataPublicPluginStart; - discover: DiscoverStart; -} diff --git a/x-pack/plugins/discover_log_explorer/server/config.ts b/x-pack/plugins/discover_log_explorer/server/config.ts deleted file mode 100644 index 0fece328c2964..0000000000000 --- a/x-pack/plugins/discover_log_explorer/server/config.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema, offeringBasedSchema } from '@kbn/config-schema'; -import { PluginConfigDescriptor } from '@kbn/core/server'; - -import { DiscoverLogExplorerConfig } from '../common/plugin_config'; - -export const configSchema = schema.object({ - featureFlags: schema.object({ - deepLinkVisible: offeringBasedSchema({ - serverless: schema.boolean(), - options: { - defaultValue: false, - }, - }), - }), -}); - -export const config: PluginConfigDescriptor = { - schema: configSchema, - exposeToBrowser: { - featureFlags: { - deepLinkVisible: true, - }, - }, -}; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/helpers/get_available_indices.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/helpers/get_available_indices.ts new file mode 100644 index 0000000000000..032a0930cb40f --- /dev/null +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/helpers/get_available_indices.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 { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; + +export const getRequestBody = ({ + indexPattern, + startDate = 'now-7d/d', + endDate = 'now/d', +}: { + indexPattern: string; + startDate: string; + endDate: string; +}): SearchRequest => ({ + index: indexPattern, + aggs: { + index: { + terms: { + field: '_index', + }, + }, + }, + size: 0, + query: { + bool: { + must: [], + filter: [ + { + range: { + '@timestamp': { + format: 'strict_date_optional_time', + gte: startDate, + lte: endDate, + }, + }, + }, + ], + should: [], + must_not: [], + }, + }, +}); diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_available_indices.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_available_indices.ts new file mode 100644 index 0000000000000..584a261689113 --- /dev/null +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_available_indices.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { ElasticsearchClient } from '@kbn/core/server'; +import { getRequestBody } from '../helpers/get_available_indices'; + +type AggregateName = 'index'; +interface Result { + index: { + buckets: Array<{ key: string }>; + doc_count: number; + }; +} + +export const fetchAvailableIndices = ( + esClient: ElasticsearchClient, + params: { indexPattern: string; startDate: string; endDate: string } +) => esClient.search(getRequestBody(params)); diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_ilm_explain.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_ilm_explain.ts index cb7d5535e217d..6ee120aa04ae3 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_ilm_explain.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_ilm_explain.ts @@ -8,7 +8,7 @@ import { IlmExplainLifecycleResponse } from '@elastic/elasticsearch/lib/api/types'; import type { IScopedClusterClient } from '@kbn/core/server'; -export const fetchILMExplain = async ( +export const fetchILMExplain = ( client: IScopedClusterClient, indexPattern: string ): Promise => diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_mappings.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_mappings.ts index aa5ca64dd565e..e0364acbb559e 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_mappings.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_mappings.ts @@ -8,7 +8,7 @@ import { IndicesGetMappingIndexMappingRecord } from '@elastic/elasticsearch/lib/api/types'; import type { IScopedClusterClient } from '@kbn/core/server'; -export const fetchMappings = async ( +export const fetchMappings = ( client: IScopedClusterClient, indexPattern: string ): Promise> => diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_stats.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_stats.ts index 2fe27f77b6154..b9a6abd7e54db 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_stats.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/fetch_stats.ts @@ -8,7 +8,7 @@ import { IndicesStatsResponse } from '@elastic/elasticsearch/lib/api/types'; import type { IScopedClusterClient } from '@kbn/core/server'; -export const fetchStats = async ( +export const fetchStats = ( client: IScopedClusterClient, indexPattern: string ): Promise => diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/lib/index.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/index.ts index 79b8d9b4f13c2..65700075ce926 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/lib/index.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/lib/index.ts @@ -9,3 +9,4 @@ export * from './fetch_mappings'; export * from './fetch_stats'; export * from './get_unallowed_field_values'; export * from './fetch_ilm_explain'; +export * from './fetch_available_indices'; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts index 8a988ef636e80..aa7fc306b47e8 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts @@ -6,7 +6,7 @@ */ import { GET_INDEX_STATS } from '../../common/constants'; -import { fetchStats } from '../lib'; +import { fetchAvailableIndices, fetchStats } from '../lib'; import { serverMock } from '../__mocks__/server'; import { requestMock } from '../__mocks__/request'; @@ -15,6 +15,7 @@ import { getIndexStatsRoute } from './get_index_stats'; jest.mock('../lib', () => ({ fetchStats: jest.fn(), + fetchAvailableIndices: jest.fn(), })); describe('getIndexStatsRoute route', () => { @@ -26,6 +27,11 @@ describe('getIndexStatsRoute route', () => { params: { pattern: 'auditbeat-*', }, + query: { + isILMAvailable: true, + startDate: `now-7d`, + endDate: `now`, + }, }); beforeEach(() => { @@ -56,6 +62,67 @@ describe('getIndexStatsRoute route', () => { expect(response.status).toEqual(500); expect(response.body).toEqual({ message: errorMessage, status_code: 500 }); }); + + test('requires date range when isILMAvailable is false', async () => { + const request = requestMock.create({ + method: 'get', + path: GET_INDEX_STATS, + params: { + pattern: `auditbeat-*`, + }, + query: { + isILMAvailable: false, + }, + }); + + const mockIndices = { 'auditbeat-7.15.1-2022.12.06-000001': {} }; + (fetchStats as jest.Mock).mockResolvedValue({ + indices: mockIndices, + }); + + const response = await server.inject(request, requestContextMock.convertContext(context)); + expect(response.status).toEqual(400); + expect(response.body.status_code).toEqual(400); + expect(response.body.message).toEqual(`startDate and endDate are required`); + }); + + test('returns available indices within the given date range when isILMAvailable is false', async () => { + const request = requestMock.create({ + method: 'get', + path: GET_INDEX_STATS, + params: { + pattern: `auditbeat-*`, + }, + query: { + isILMAvailable: false, + startDate: `now-7d`, + endDate: `now`, + }, + }); + + const mockIndices = { + 'auditbeat-7.15.1-2022.12.06-000001': {}, + 'auditbeat-7.15.1-2022.11.06-000001': {}, + }; + (fetchStats as jest.Mock).mockResolvedValue({ + indices: mockIndices, + }); + (fetchAvailableIndices as jest.Mock).mockResolvedValue({ + aggregations: { + index: { + buckets: [ + { + key: 'auditbeat-7.15.1-2022.12.06-000001', + }, + ], + }, + }, + }); + + const response = await server.inject(request, requestContextMock.convertContext(context)); + expect(response.status).toEqual(200); + expect(response.body).toEqual({ 'auditbeat-7.15.1-2022.12.06-000001': {} }); + }); }); describe('request validation', () => { diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts index 221a07699f69c..839d21931a064 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts @@ -4,37 +4,83 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import { i18n } from '@kbn/i18n'; import { IRouter } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; -import { fetchStats } from '../lib'; +import { IndicesStatsIndicesStats } from '@elastic/elasticsearch/lib/api/types'; +import { fetchStats, fetchAvailableIndices } from '../lib'; import { buildResponse } from '../lib/build_response'; import { GET_INDEX_STATS } from '../../common/constants'; import { buildRouteValidation } from '../schemas/common'; -import { GetIndexStatsParams } from '../schemas/get_index_stats'; +import { GetIndexStatsParams, GetIndexStatsQuery } from '../schemas/get_index_stats'; export const getIndexStatsRoute = (router: IRouter) => { router.get( { path: GET_INDEX_STATS, - validate: { params: buildRouteValidation(GetIndexStatsParams) }, + validate: { + params: buildRouteValidation(GetIndexStatsParams), + query: buildRouteValidation(GetIndexStatsQuery), + }, }, async (context, request, response) => { const resp = buildResponse(response); try { const { client } = (await context.core).elasticsearch; + const esClient = client.asCurrentUser; + const decodedIndexName = decodeURIComponent(request.params.pattern); const stats = await fetchStats(client, decodedIndexName); + const { isILMAvailable, startDate, endDate } = request.query; - return response.ok({ - body: stats.indices, - }); + if (isILMAvailable === true) { + return response.ok({ + body: stats.indices, + }); + } + + /** + * If ILM is not available, we need to fetch the available indices with the given date range. + * `fetchAvailableIndices` returns indices that have data in the given date range. + */ + if (startDate && endDate) { + const decodedStartDate = decodeURIComponent(startDate); + const decodedEndDate = decodeURIComponent(endDate); + + const indices = await fetchAvailableIndices(esClient, { + indexPattern: decodedIndexName, + startDate: decodedStartDate, + endDate: decodedEndDate, + }); + const availableIndices = indices?.aggregations?.index?.buckets?.reduce( + (acc: Record, { key }: { key: string }) => { + if (stats.indices?.[key]) { + acc[key] = stats.indices?.[key]; + } + return acc; + }, + {} + ); + + return response.ok({ + body: availableIndices, + }); + } else { + return resp.error({ + body: i18n.translate( + 'xpack.ecsDataQualityDashboard.getIndexStats.dateRangeRequiredErrorMessage', + { + defaultMessage: 'startDate and endDate are required', + } + ), + statusCode: 400, + }); + } } catch (err) { const error = transformError(err); - return resp.error({ body: error.message, statusCode: error.statusCode, diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/get_index_stats.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/get_index_stats.ts index ee4a2694ec500..432f863fe9dfc 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/get_index_stats.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/get_index_stats.ts @@ -6,7 +6,14 @@ */ import * as t from 'io-ts'; +import { DefaultStringBooleanFalse } from '@kbn/securitysolution-io-ts-types'; export const GetIndexStatsParams = t.type({ pattern: t.string, }); + +export const GetIndexStatsQuery = t.type({ + isILMAvailable: DefaultStringBooleanFalse, + startDate: t.union([t.string, t.null, t.undefined]), + endDate: t.union([t.string, t.null, t.undefined]), +}); diff --git a/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json b/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json index 98177ac09c384..b5c1ad152b232 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json +++ b/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json @@ -18,6 +18,8 @@ "@kbn/core-http-request-handler-context-server", "@kbn/securitysolution-es-utils", "@kbn/securitysolution-io-ts-utils", + "@kbn/securitysolution-io-ts-types", + "@kbn/i18n", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/elastic_assistant/README.md b/x-pack/plugins/elastic_assistant/README.md new file mode 100755 index 0000000000000..e0fef329abc08 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/README.md @@ -0,0 +1,9 @@ +# Elastic AI Assistant + +This plugin implements (only) server APIs for the `Elastic AI Assistant`. + +This plugin does NOT contain UI components. See `x-pack/packages/kbn-elastic-assistant` for React components. + +## Maintainers + +Maintained by the Security Solution team diff --git a/x-pack/plugins/elastic_assistant/common/constants.ts b/x-pack/plugins/elastic_assistant/common/constants.ts new file mode 100755 index 0000000000000..c6c6f2419a182 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const PLUGIN_ID = 'elasticAssistant'; +export const PLUGIN_NAME = 'elasticAssistant'; + +export const BASE_PATH = '/internal/elastic_assistant'; + +export const POST_ACTIONS_CONNECTOR_EXECUTE = `${BASE_PATH}/actions/connector/{connectorId}/_execute`; diff --git a/x-pack/plugins/discover_log_explorer/jest.config.js b/x-pack/plugins/elastic_assistant/jest.config.js similarity index 71% rename from x-pack/plugins/discover_log_explorer/jest.config.js rename to x-pack/plugins/elastic_assistant/jest.config.js index 988de065d4013..7bbeb3b1c89d2 100644 --- a/x-pack/plugins/discover_log_explorer/jest.config.js +++ b/x-pack/plugins/elastic_assistant/jest.config.js @@ -6,12 +6,12 @@ */ module.exports = { - preset: '@kbn/test', - rootDir: '../../..', - roots: ['/x-pack/plugins/discover_log_explorer'], - coverageDirectory: '/target/kibana-coverage/jest/x-pack/plugins/discover_log_explorer', - coverageReporters: ['text', 'html'], collectCoverageFrom: [ - '/x-pack/plugins/discover_log_explorer/{common,public}/**/*.{ts,tsx}', + '/x-pack/plugins/elastic_assistant/{common,lib,server}/**/*.{ts,tsx}', ], + coverageDirectory: '/target/kibana-coverage/jest/x-pack/plugins/elastic_assistant', + coverageReporters: ['text', 'html'], + rootDir: '../../..', + roots: ['/x-pack/plugins/elastic_assistant'], + preset: '@kbn/test', }; diff --git a/x-pack/plugins/elastic_assistant/kibana.jsonc b/x-pack/plugins/elastic_assistant/kibana.jsonc new file mode 100644 index 0000000000000..d7518cf600983 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/kibana.jsonc @@ -0,0 +1,15 @@ +{ + "type": "plugin", + "id": "@kbn/elastic-assistant-plugin", + "owner": "@elastic/security-solution", + "description": "Server APIs for the Elastic AI Assistant", + "plugin": { + "id": "elasticAssistant", + "server": true, + "browser": false, + "requiredPlugins": [ + "actions", + "data" + ] + } +} diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/action_result_data.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/action_result_data.ts new file mode 100644 index 0000000000000..280a86d2ac326 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/action_result_data.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. + */ + +/** + * A mock `data` property from an `actionResult` response, which is returned + * from the `execute` method of the Actions plugin. + * + * Given the following example: + * + * ```ts + * const actionResult = await actionsClient.execute(requestBody); + * ``` + * + * In the above example, `actionResult.data` would be this mock data. + */ +export const mockActionResultData = { + id: 'chatcmpl-7sFVvksgFtMUac3pY5bTypFAKaGX1', + object: 'chat.completion', + created: 1693163703, + model: 'gpt-4', + choices: [ + { + index: 0, + finish_reason: 'stop', + message: { + role: 'assistant', + content: 'Yes, your name is Andrew. How can I assist you further, Andrew?', + }, + }, + ], + usage: { completion_tokens: 16, prompt_tokens: 140, total_tokens: 156 }, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/lang_chain_messages.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/lang_chain_messages.ts new file mode 100644 index 0000000000000..bbf32c714065f --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/lang_chain_messages.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 { AIMessage, BaseMessage, HumanMessage } from 'langchain/schema'; + +export const langChainMessages: BaseMessage[] = [ + new HumanMessage('What is my name?'), + new AIMessage( + "I'm sorry, but I am not able to answer questions unrelated to Elastic Security. If you have any questions about Elastic Security, please feel free to ask." + ), + new HumanMessage('\n\nMy name is Andrew'), + new AIMessage( + "Hello Andrew! If you have any questions about Elastic Security, feel free to ask, and I'll do my best to help you." + ), + new HumanMessage('\n\nDo you know my name?'), +]; diff --git a/x-pack/test/security_solution_cypress/cypress/tags.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts similarity index 66% rename from x-pack/test/security_solution_cypress/cypress/tags.ts rename to x-pack/plugins/elastic_assistant/server/__mocks__/request.ts index a0698a4c40951..827f08683e0b8 100644 --- a/x-pack/test/security_solution_cypress/cypress/tags.ts +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts @@ -4,9 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { httpServerMock } from '@kbn/core/server/mocks'; -export const tag = { - SERVERLESS: '@serverless', - ESS: '@ess', - BROKEN_IN_SERVERLESS: '@brokenInServerless', +export const requestMock = { + create: httpServerMock.createKibanaRequest, }; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts new file mode 100644 index 0000000000000..19fb44f7f8bac --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.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 { coreMock } from '@kbn/core/server/mocks'; +import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; + +export const createMockClients = () => { + const core = coreMock.createRequestHandlerContext(); + const license = licensingMock.createLicenseMock(); + + return { + core, + clusterClient: core.elasticsearch.client, + savedObjectsClient: core.savedObjects.client, + + licensing: { + ...licensingMock.createRequestHandlerContext({ license }), + license, + }, + + config: createMockConfig(), + appClient: createAppClientMock(), + }; +}; + +type MockClients = ReturnType; + +const convertRequestContextMock = (context: T) => { + return coreMock.createCustomRequestHandlerContext(context); +}; + +const createMockConfig = () => ({}); + +const createAppClientMock = () => ({}); + +const createRequestContextMock = (clients: MockClients = createMockClients()) => { + return { + core: clients.core, + }; +}; + +const createTools = () => { + const clients = createMockClients(); + const context = createRequestContextMock(clients); + + return { clients, context }; +}; + +export const requestContextMock = { + create: createRequestContextMock, + convertContext: convertRequestContextMock, + createTools, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts new file mode 100644 index 0000000000000..8efe2407f2245 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { httpServerMock } from '@kbn/core/server/mocks'; + +export const responseMock = { + create: httpServerMock.createResponseFactory, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/server.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/server.ts new file mode 100644 index 0000000000000..7ac44e1beedf1 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/server.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 { httpServiceMock } from '@kbn/core/server/mocks'; +import type { RequestHandler, RouteConfig, KibanaRequest } from '@kbn/core/server'; +import type { RequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; + +import { requestMock } from './request'; +import { responseMock as responseFactoryMock } from './response'; +import { requestContextMock } from './request_context'; +import { responseAdapter } from './test_adapters'; + +interface Route { + config: RouteConfig; + handler: RequestHandler; +} + +const getRoute = (routerMock: MockServer['router']): Route => { + const routeCalls = [ + ...routerMock.get.mock.calls, + ...routerMock.post.mock.calls, + ...routerMock.put.mock.calls, + ...routerMock.patch.mock.calls, + ...routerMock.delete.mock.calls, + ]; + + const [route] = routeCalls; + if (!route) { + throw new Error('No route registered!'); + } + + const [config, handler] = route; + return { config, handler }; +}; + +const buildResultMock = () => ({ ok: jest.fn((x) => x), badRequest: jest.fn((x) => x) }); + +class MockServer { + constructor( + public readonly router = httpServiceMock.createRouter(), + private responseMock = responseFactoryMock.create(), + private contextMock = requestContextMock.convertContext(requestContextMock.create()), + private resultMock = buildResultMock() + ) {} + + public validate(request: KibanaRequest) { + this.validateRequest(request); + return this.resultMock; + } + + public async inject(request: KibanaRequest, context: RequestHandlerContext = this.contextMock) { + const validatedRequest = this.validateRequest(request); + const [rejection] = this.resultMock.badRequest.mock.calls; + if (rejection) { + throw new Error(`Request was rejected with message: '${rejection}'`); + } + + await this.getRoute().handler(context, validatedRequest, this.responseMock); + return responseAdapter(this.responseMock); + } + + private getRoute(): Route { + return getRoute(this.router); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private maybeValidate(part: any, validator?: any): any { + return typeof validator === 'function' ? validator(part, this.resultMock) : part; + } + + private validateRequest(request: KibanaRequest): KibanaRequest { + const validations = this.getRoute().config.validate; + if (!validations) { + return request; + } + + const validatedRequest = requestMock.create({ + path: request.route.path, + method: request.route.method, + body: this.maybeValidate(request.body, validations.body), + query: this.maybeValidate(request.query, validations.query), + params: this.maybeValidate(request.params, validations.params), + }); + + return validatedRequest; + } +} +const createMockServer = () => new MockServer(); + +export const serverMock = { + create: createMockServer, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/test_adapters.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/test_adapters.ts new file mode 100644 index 0000000000000..4de81ca931692 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/test_adapters.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 type { responseMock } from './response'; + +type ResponseMock = ReturnType; +type Method = keyof ResponseMock; + +type MockCall = any; // eslint-disable-line @typescript-eslint/no-explicit-any + +interface ResponseCall { + body: any; // eslint-disable-line @typescript-eslint/no-explicit-any + status: number; +} + +/** + * @internal + */ +export interface Response extends ResponseCall { + calls: ResponseCall[]; +} + +const buildResponses = (method: Method, calls: MockCall[]): ResponseCall[] => { + if (!calls.length) return []; + + switch (method) { + case 'ok': + return calls.map(([call]) => ({ status: 200, body: call.body })); + case 'custom': + return calls.map(([call]) => ({ + status: call.statusCode, + body: JSON.parse(call.body), + })); + case 'customError': + return calls.map(([call]) => ({ + status: call.statusCode, + body: call.body, + })); + default: + throw new Error(`Encountered unexpected call to response.${method}`); + } +}; + +export const responseAdapter = (response: ResponseMock): Response => { + const methods = Object.keys(response) as Method[]; + const calls = methods + .reduce((responses, method) => { + const methodMock = response[method]; + return [...responses, ...buildResponses(method, methodMock.mock.calls)]; + }, []) + .sort((call, other) => other.status - call.status); + + const [{ body, status }] = calls; + + return { + body, + status, + calls, + }; +}; diff --git a/x-pack/plugins/elastic_assistant/server/index.ts b/x-pack/plugins/elastic_assistant/server/index.ts new file mode 100755 index 0000000000000..a375e036d8238 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PluginInitializerContext } from '@kbn/core/server'; +import { ElasticAssistantPlugin } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new ElasticAssistantPlugin(initializerContext); +} + +export type { + ElasticAssistantPluginSetup as EcsDataQualityDashboardPluginSetup, + ElasticAssistantPluginStart as EcsDataQualityDashboardPluginStart, +} from './types'; diff --git a/x-pack/plugins/elastic_assistant/server/lib/build_response/index.ts b/x-pack/plugins/elastic_assistant/server/lib/build_response/index.ts new file mode 100644 index 0000000000000..bbec702c74915 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/build_response/index.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 type { CustomHttpResponseOptions, KibanaResponseFactory } from '@kbn/core-http-server'; + +const statusToErrorMessage = ( + statusCode: number +): + | 'Bad Request' + | 'Unauthorized' + | 'Forbidden' + | 'Not Found' + | 'Conflict' + | 'Internal Error' + | '(unknown error)' => { + switch (statusCode) { + case 400: + return 'Bad Request'; + case 401: + return 'Unauthorized'; + case 403: + return 'Forbidden'; + case 404: + return 'Not Found'; + case 409: + return 'Conflict'; + case 500: + return 'Internal Error'; + default: + return '(unknown error)'; + } +}; + +/** Creates responses */ +export class ResponseFactory { + /** constructor */ + constructor(private response: KibanaResponseFactory) {} + + /** error */ + error({ statusCode, body, headers }: CustomHttpResponseOptions) { + const contentType: CustomHttpResponseOptions['headers'] = { + 'content-type': 'application/json', + }; + const defaultedHeaders: CustomHttpResponseOptions['headers'] = { + ...contentType, + ...(headers ?? {}), + }; + + return this.response.custom({ + body: Buffer.from( + JSON.stringify({ + message: body ?? statusToErrorMessage(statusCode), + status_code: statusCode, + }) + ), + headers: defaultedHeaders, + statusCode, + }); + } +} + +/** builds a response */ +export const buildResponse = (response: KibanaResponseFactory): ResponseFactory => + new ResponseFactory(response); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.test.ts new file mode 100644 index 0000000000000..b6c4dd3917585 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.test.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 { KibanaRequest } from '@kbn/core/server'; +import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; + +import { ResponseBody } from '../helpers'; +import { ActionsClientLlm } from '../llm/actions_client_llm'; +import { mockActionResultData } from '../../../__mocks__/action_result_data'; +import { langChainMessages } from '../../../__mocks__/lang_chain_messages'; +import { executeCustomLlmChain } from '.'; + +jest.mock('../llm/actions_client_llm'); + +const mockConversationChain = { + call: jest.fn(), +}; + +jest.mock('langchain/chains', () => ({ + ConversationChain: jest.fn().mockImplementation(() => mockConversationChain), +})); + +const mockConnectorId = 'mock-connector-id'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const mockRequest: KibanaRequest = {} as KibanaRequest< + unknown, + unknown, + any, // eslint-disable-line @typescript-eslint/no-explicit-any + any // eslint-disable-line @typescript-eslint/no-explicit-any +>; + +const mockActions: ActionsPluginStart = {} as ActionsPluginStart; + +describe('executeCustomLlmChain', () => { + beforeEach(() => { + jest.clearAllMocks(); + + ActionsClientLlm.prototype.getActionResultData = jest + .fn() + .mockReturnValueOnce(mockActionResultData); + }); + + it('creates an instance of ActionsClientLlm with the expected context from the request', async () => { + await executeCustomLlmChain({ + actions: mockActions, + connectorId: mockConnectorId, + langChainMessages, + request: mockRequest, + }); + + expect(ActionsClientLlm).toHaveBeenCalledWith({ + actions: mockActions, + connectorId: mockConnectorId, + request: mockRequest, + }); + }); + + it('kicks off the chain with (only) the last message', async () => { + await executeCustomLlmChain({ + actions: mockActions, + connectorId: mockConnectorId, + langChainMessages, + request: mockRequest, + }); + + expect(mockConversationChain.call).toHaveBeenCalledWith({ + input: '\n\nDo you know my name?', + }); + }); + + it('kicks off the chain with the expected message when langChainMessages has only one entry', async () => { + const onlyOneMessage = [langChainMessages[0]]; + + await executeCustomLlmChain({ + actions: mockActions, + connectorId: mockConnectorId, + langChainMessages: onlyOneMessage, + request: mockRequest, + }); + + expect(mockConversationChain.call).toHaveBeenCalledWith({ + input: 'What is my name?', + }); + }); + + it('returns the expected response body', async () => { + const result: ResponseBody = await executeCustomLlmChain({ + actions: mockActions, + connectorId: mockConnectorId, + langChainMessages, + request: mockRequest, + }); + + expect(result).toEqual({ + connector_id: 'mock-connector-id', + data: mockActionResultData, + status: 'ok', + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.ts new file mode 100644 index 0000000000000..ee7b6820c983d --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/execute_custom_llm_chain/index.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 { KibanaRequest } from '@kbn/core/server'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import { ConversationChain } from 'langchain/chains'; +import { BufferMemory, ChatMessageHistory } from 'langchain/memory'; +import { BaseMessage } from 'langchain/schema'; + +import { ActionsClientLlm } from '../llm/actions_client_llm'; +import { ResponseBody } from '../helpers'; + +export const executeCustomLlmChain = async ({ + actions, + connectorId, + langChainMessages, + request, +}: { + actions: ActionsPluginStart; + connectorId: string; + langChainMessages: BaseMessage[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + request: KibanaRequest; +}): Promise => { + const llm = new ActionsClientLlm({ actions, connectorId, request }); + + const pastMessages = langChainMessages.slice(0, -1); // all but the last message + const latestMessage = langChainMessages.slice(-1); // the last message + + const memory = new BufferMemory({ + chatHistory: new ChatMessageHistory(pastMessages), + }); + + const chain = new ConversationChain({ llm, memory }); + + await chain.call({ input: latestMessage[0].content }); // kick off the chain with the last message + + // The assistant (on the client side) expects the same response returned + // from the actions framework, so we need to return the same shape of data: + const responseBody = { + connector_id: connectorId, + data: llm.getActionResultData(), // the response from the actions framework + status: 'ok', + }; + + return responseBody; +}; diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.test.ts new file mode 100644 index 0000000000000..1c62fab9df6cc --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.test.ts @@ -0,0 +1,185 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Message } from '@kbn/elastic-assistant'; +import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from 'langchain/schema'; + +import { + getLangChainMessage, + getLangChainMessages, + getMessageContentAndRole, + unsafeGetAssistantMessagesFromRequest, +} from './helpers'; +import { langChainMessages } from '../../__mocks__/lang_chain_messages'; + +describe('helpers', () => { + describe('getLangChainMessage', () => { + const testCases: Array<[Pick, typeof BaseMessage]> = [ + [ + { + role: 'system', + content: 'System message', + }, + SystemMessage, + ], + [ + { + role: 'user', + content: 'User message', + }, + HumanMessage, + ], + [ + { + role: 'assistant', + content: 'Assistant message', + }, + AIMessage, + ], + [ + { + role: 'unknown' as Message['role'], + content: 'Unknown message', + }, + HumanMessage, + ], + ]; + + testCases.forEach(([testCase, expectedClass]) => { + it(`returns the expected content when role is ${testCase.role}`, () => { + const result = getLangChainMessage(testCase); + + expect(result.content).toEqual(testCase.content); + }); + + it(`returns the expected BaseMessage instance when role is ${testCase.role}`, () => { + const result = getLangChainMessage(testCase); + + expect(result instanceof expectedClass).toBeTruthy(); + }); + }); + }); + + describe('getLangChainMessages', () => { + const assistantMessages: Array> = [ + { + content: 'What is my name?', + role: 'user', + }, + { + content: + "I'm sorry, but I am not able to answer questions unrelated to Elastic Security. If you have any questions about Elastic Security, please feel free to ask.", + role: 'assistant', + }, + { + content: '\n\nMy name is Andrew', + role: 'user', + }, + { + content: + "Hello Andrew! If you have any questions about Elastic Security, feel free to ask, and I'll do my best to help you.", + role: 'assistant', + }, + { + content: '\n\nDo you know my name?', + role: 'user', + }, + ]; + + it('returns the expected BaseMessage instances', () => { + expect(getLangChainMessages(assistantMessages)).toEqual(langChainMessages); + }); + }); + + describe('getMessageContentAndRole', () => { + const testCases: Array<[string, Pick]> = [ + ['Prompt 1', { content: 'Prompt 1', role: 'user' }], + ['Prompt 2', { content: 'Prompt 2', role: 'user' }], + ['', { content: '', role: 'user' }], + ]; + + testCases.forEach(([prompt, expectedOutput]) => { + test(`Given the prompt "${prompt}", it returns the prompt as content with a "user" role`, () => { + const result = getMessageContentAndRole(prompt); + + expect(result).toEqual(expectedOutput); + }); + }); + }); + + describe('unsafeGetAssistantMessagesFromRequest', () => { + const rawSubActionParamsBody = { + messages: [ + { role: 'user', content: '\n\n\n\nWhat is my name?' }, + { + role: 'assistant', + content: + "Hello! Since we are communicating through text, I do not have the information about your name. Please feel free to share your name with me, if you'd like.", + }, + { role: 'user', content: '\n\nMy name is Andrew' }, + { + role: 'assistant', + content: + "Hi, Andrew! It's nice to meet you. How can I help you or what would you like to talk about today?", + }, + { role: 'user', content: '\n\nDo you know my name?' }, + ], + }; + + it('returns the expected assistant messages from a conversation', () => { + const result = unsafeGetAssistantMessagesFromRequest(JSON.stringify(rawSubActionParamsBody)); + + const expected = [ + { role: 'user', content: '\n\n\n\nWhat is my name?' }, + { + role: 'assistant', + content: + "Hello! Since we are communicating through text, I do not have the information about your name. Please feel free to share your name with me, if you'd like.", + }, + { role: 'user', content: '\n\nMy name is Andrew' }, + { + role: 'assistant', + content: + "Hi, Andrew! It's nice to meet you. How can I help you or what would you like to talk about today?", + }, + { role: 'user', content: '\n\nDo you know my name?' }, + ]; + + expect(result).toEqual(expected); + }); + + it('returns an empty array when the rawSubActionParamsBody is undefined', () => { + const result = unsafeGetAssistantMessagesFromRequest(undefined); + + expect(result).toEqual([]); + }); + + it('returns an empty array when the rawSubActionParamsBody messages[] array is empty', () => { + const hasEmptyMessages = { + messages: [], + }; + + const result = unsafeGetAssistantMessagesFromRequest(JSON.stringify(hasEmptyMessages)); + + expect(result).toEqual([]); + }); + + it('returns an empty array when the rawSubActionParamsBody shape is unexpected', () => { + const unexpected = { invalidKey: 'some_value' }; + + const result = unsafeGetAssistantMessagesFromRequest(JSON.stringify(unexpected)); + + expect(result).toEqual([]); + }); + + it('returns an empty array when the rawSubActionParamsBody is invalid JSON', () => { + const result = unsafeGetAssistantMessagesFromRequest('[]'); + + expect(result).toEqual([]); + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.ts new file mode 100644 index 0000000000000..90364dcfe75db --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/helpers.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Message } from '@kbn/elastic-assistant'; +import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from 'langchain/schema'; + +export const getLangChainMessage = ( + assistantMessage: Pick +): BaseMessage => { + switch (assistantMessage.role) { + case 'system': + return new SystemMessage(assistantMessage.content); + case 'user': + return new HumanMessage(assistantMessage.content); + case 'assistant': + return new AIMessage(assistantMessage.content); + default: + return new HumanMessage(assistantMessage.content); + } +}; + +export const getLangChainMessages = ( + assistantMessages: Array> +): BaseMessage[] => assistantMessages.map(getLangChainMessage); + +export const getMessageContentAndRole = (prompt: string): Pick => ({ + content: prompt, + role: 'user', +}); + +export interface ResponseBody { + status: string; + data: Record; + connector_id: string; +} + +/** An unsafe, temporary stub that parses assistant messages from the request with no validation */ +export const unsafeGetAssistantMessagesFromRequest = ( + rawSubActionParamsBody: string | undefined +): Array> => { + try { + if (rawSubActionParamsBody == null) { + return []; + } + + const subActionParamsBody = JSON.parse(rawSubActionParamsBody); // TODO: unsafe, no validation + const messages = subActionParamsBody?.messages; + + return Array.isArray(messages) ? messages : []; + } catch { + return []; + } +}; diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.test.ts new file mode 100644 index 0000000000000..289793de859c0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.test.ts @@ -0,0 +1,172 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { KibanaRequest } from '@kbn/core/server'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; + +import { ActionsClientLlm } from './actions_client_llm'; +import { mockActionResultData } from '../../../__mocks__/action_result_data'; + +const connectorId = 'mock-connector-id'; + +const mockExecute = jest.fn().mockImplementation(() => ({ + data: mockActionResultData, + status: 'ok', +})); + +const mockActions = { + getActionsClientWithRequest: jest.fn().mockImplementation(() => ({ + execute: mockExecute, + })), +} as unknown as ActionsPluginStart; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const mockRequest: KibanaRequest = { + params: { connectorId }, + body: { + params: { + subActionParams: { + body: '{"messages":[{"role":"user","content":"\\n\\n\\n\\nWhat is my name?"},{"role":"assistant","content":"I\'m sorry, but I don\'t have the information about your name. You can tell me your name if you\'d like, and we can continue our conversation from there."},{"role":"user","content":"\\n\\nMy name is Andrew"},{"role":"assistant","content":"Hello, Andrew! It\'s nice to meet you. What would you like to talk about today?"},{"role":"user","content":"\\n\\nDo you know my name?"}]}', + }, + subAction: 'test', + }, + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any +} as KibanaRequest; + +const prompt = 'Do you know my name?'; + +describe('ActionsClientLlm', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('getActionResultData', () => { + it('returns the expected data', async () => { + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + await actionsClientLlm._call(prompt); // ignore the result + + expect(actionsClientLlm.getActionResultData()).toEqual(mockActionResultData); + }); + }); + + describe('_llmType', () => { + it('returns the expected LLM type', () => { + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + expect(actionsClientLlm._llmType()).toEqual('ActionsClientLlm'); + }); + }); + + describe('_call', () => { + it('returns the expected content when _call is invoked', async () => { + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + const result = await actionsClientLlm._call(prompt); + + expect(result).toEqual('Yes, your name is Andrew. How can I assist you further, Andrew?'); + }); + + it('rejects with the expected error when the action result status is error', async () => { + const hasErrorStatus = jest.fn().mockImplementation(() => ({ + message: 'action-result-message', + serviceMessage: 'action-result-service-message', + status: 'error', // <-- error status + })); + + const badActions = { + getActionsClientWithRequest: jest.fn().mockImplementation(() => ({ + execute: hasErrorStatus, + })), + } as unknown as ActionsPluginStart; + + const actionsClientLlm = new ActionsClientLlm({ + actions: badActions, + connectorId, + request: mockRequest, + }); + + expect(actionsClientLlm._call(prompt)).rejects.toThrowError( + 'ActionsClientLlm: action result status is error: action-result-message - action-result-service-message' + ); + }); + + it('rejects with the expected error the message has invalid content', async () => { + const invalidContent = { + id: 'chatcmpl-7sFVvksgFtMUac3pY5bTypFAKaGX1', + object: 'chat.completion', + created: 1693163703, + model: 'gpt-4', + choices: [ + { + index: 0, + finish_reason: 'stop', + message: { + role: 'assistant', + content: 1234, // <-- invalid content + }, + }, + ], + usage: { completion_tokens: 16, prompt_tokens: 140, total_tokens: 156 }, + }; + + mockExecute.mockImplementation(() => ({ + data: invalidContent, + status: 'ok', + })); + + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + expect(actionsClientLlm._call(prompt)).rejects.toThrowError( + 'ActionsClientLlm: choices[0] message content should be a string, but it had an unexpected type: number' + ); + }); + + it('rejects with the expected error when choices is empty', async () => { + const invalidContent = { + id: 'chatcmpl-7sFVvksgFtMUac3pY5bTypFAKaGX1', + object: 'chat.completion', + created: 1693163703, + model: 'gpt-4', + choices: [], // <-- empty choices + usage: { completion_tokens: 16, prompt_tokens: 140, total_tokens: 156 }, + }; + + mockExecute.mockImplementation(() => ({ + data: invalidContent, + status: 'ok', + })); + + const actionsClientLlm = new ActionsClientLlm({ + actions: mockActions, + connectorId, + request: mockRequest, + }); + + expect(actionsClientLlm._call(prompt)).rejects.toThrowError( + 'ActionsClientLlm: choices is expected to be an non-empty array' + ); + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.ts new file mode 100644 index 0000000000000..00d78dc6cb309 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/llm/actions_client_llm.ts @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { KibanaRequest } from '@kbn/core/server'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import { LLM } from 'langchain/llms/base'; +import { get } from 'lodash/fp'; + +import { getMessageContentAndRole } from '../helpers'; + +const LLM_TYPE = 'ActionsClientLlm'; + +export class ActionsClientLlm extends LLM { + #actions: ActionsPluginStart; + #connectorId: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + #request: KibanaRequest; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + #actionResultData: Record; + + constructor({ + actions, + connectorId, + request, + }: { + actions: ActionsPluginStart; + connectorId: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + request: KibanaRequest; + }) { + super({}); + + this.#actions = actions; + this.#connectorId = connectorId; + this.#request = request; + this.#actionResultData = {}; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + getActionResultData(): Record { + return this.#actionResultData; + } + + _llmType() { + return LLM_TYPE; + } + + async _call(prompt: string): Promise { + // convert the Langchain prompt to an assistant message: + const assistantMessage = getMessageContentAndRole(prompt); + + // create a new connector request body with the assistant message: + const requestBody = { + actionId: this.#connectorId, + params: { + ...this.#request.body.params, // the original request body params + subActionParams: { + ...this.#request.body.params.subActionParams, // the original request body params.subActionParams + body: JSON.stringify({ messages: [assistantMessage] }), + }, + }, + }; + + // create an actions client from the authenticated request context: + const actionsClient = await this.#actions.getActionsClientWithRequest(this.#request); + + const actionResult = await actionsClient.execute(requestBody); + + if (actionResult.status === 'error') { + throw new Error( + `${LLM_TYPE}: action result status is error: ${actionResult?.message} - ${actionResult?.serviceMessage}` + ); + } + + const choices = get('data.choices', actionResult); + + if (Array.isArray(choices) && choices.length > 0) { + // get the raw content from the first choice, because _call must return a string + const content: string | undefined = choices[0]?.message?.content; + + if (typeof content !== 'string') { + throw new Error( + `${LLM_TYPE}: choices[0] message content should be a string, but it had an unexpected type: ${typeof content}` + ); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.#actionResultData = actionResult.data as Record; // save the raw response from the connector, because that's what the assistant expects + + return content; // per the contact of _call, return a string + } else { + throw new Error(`${LLM_TYPE}: choices is expected to be an non-empty array`); + } + } +} diff --git a/x-pack/plugins/elastic_assistant/server/plugin.ts b/x-pack/plugins/elastic_assistant/server/plugin.ts new file mode 100755 index 0000000000000..4e277132e8da0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/plugin.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + PluginInitializerContext, + CoreSetup, + CoreStart, + Plugin, + Logger, + IContextProvider, +} from '@kbn/core/server'; + +import { + ElasticAssistantPluginSetup, + ElasticAssistantPluginSetupDependencies, + ElasticAssistantPluginStart, + ElasticAssistantPluginStartDependencies, + ElasticAssistantRequestHandlerContext, +} from './types'; +import { postActionsConnectorExecuteRoute } from './routes'; + +export class ElasticAssistantPlugin + implements + Plugin< + ElasticAssistantPluginSetup, + ElasticAssistantPluginStart, + ElasticAssistantPluginSetupDependencies, + ElasticAssistantPluginStartDependencies + > +{ + private readonly logger: Logger; + + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get(); + } + + private createRouteHandlerContext = ( + core: CoreSetup + ): IContextProvider => { + return async function elasticAssistantRouteHandlerContext(context, request) { + const [_, pluginsStart] = await core.getStartServices(); + + return { + actions: pluginsStart.actions, + }; + }; + }; + + public setup(core: CoreSetup, plugins: ElasticAssistantPluginSetupDependencies) { + this.logger.debug('elasticAssistant: Setup'); + const router = core.http.createRouter(); + + core.http.registerRouteHandlerContext< + ElasticAssistantRequestHandlerContext, + 'elasticAssistant' + >( + 'elasticAssistant', + this.createRouteHandlerContext(core as CoreSetup) + ); + + postActionsConnectorExecuteRoute(router); + return { + actions: plugins.actions, + }; + } + + public start(core: CoreStart, plugins: ElasticAssistantPluginStartDependencies) { + this.logger.debug('elasticAssistant: Started'); + + return { + actions: plugins.actions, + }; + } + + public stop() {} +} diff --git a/x-pack/plugins/elastic_assistant/server/routes/index.ts b/x-pack/plugins/elastic_assistant/server/routes/index.ts new file mode 100644 index 0000000000000..b6a53787763a0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { postActionsConnectorExecuteRoute } from './post_actions_connector_execute'; diff --git a/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.test.ts b/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.test.ts new file mode 100644 index 0000000000000..a5934ffb8a7a7 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.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 { IRouter, KibanaRequest } from '@kbn/core/server'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import { BaseMessage } from 'langchain/schema'; + +import { mockActionResultData } from '../__mocks__/action_result_data'; +import { postActionsConnectorExecuteRoute } from './post_actions_connector_execute'; +import { ElasticAssistantRequestHandlerContext } from '../types'; + +jest.mock('../lib/build_response', () => ({ + buildResponse: jest.fn().mockImplementation((x) => x), +})); + +jest.mock('../lib/langchain/execute_custom_llm_chain', () => ({ + executeCustomLlmChain: jest.fn().mockImplementation( + async ({ + connectorId, + }: { + actions: ActionsPluginStart; + connectorId: string; + langChainMessages: BaseMessage[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + request: KibanaRequest; + }) => { + if (connectorId === 'mock-connector-id') { + return { + connector_id: 'mock-connector-id', + data: mockActionResultData, + status: 'ok', + }; + } else { + throw new Error('simulated error'); + } + } + ), +})); + +const mockContext = { + elasticAssistant: async () => ({ + actions: jest.fn(), + }), +}; + +const mockRequest = { + params: { connectorId: 'mock-connector-id' }, + body: { + params: { + subActionParams: { + body: '{"messages":[{"role":"user","content":"\\n\\n\\n\\nWhat is my name?"},{"role":"assistant","content":"I\'m sorry, but I don\'t have the information about your name. You can tell me your name if you\'d like, and we can continue our conversation from there."},{"role":"user","content":"\\n\\nMy name is Andrew"},{"role":"assistant","content":"Hello, Andrew! It\'s nice to meet you. What would you like to talk about today?"},{"role":"user","content":"\\n\\nDo you know my name?"}]}', + }, + subAction: 'test', + }, + }, +}; + +const mockResponse = { + ok: jest.fn().mockImplementation((x) => x), + error: jest.fn().mockImplementation((x) => x), +}; + +describe('postActionsConnectorExecuteRoute', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns the expected response', async () => { + const mockRouter = { + post: jest.fn().mockImplementation(async (_, handler) => { + const result = await handler(mockContext, mockRequest, mockResponse); + + expect(result).toEqual({ + body: { + connector_id: 'mock-connector-id', + data: mockActionResultData, + status: 'ok', + }, + }); + }), + }; + + await postActionsConnectorExecuteRoute( + mockRouter as unknown as IRouter + ); + }); + + it('returns the expected error when executeCustomLlmChain fails', async () => { + const requestWithBadConnectorId = { + ...mockRequest, + params: { connectorId: 'bad-connector-id' }, + }; + + const mockRouter = { + post: jest.fn().mockImplementation(async (_, handler) => { + const result = await handler(mockContext, requestWithBadConnectorId, mockResponse); + + expect(result).toEqual({ + body: 'simulated error', + statusCode: 500, + }); + }), + }; + + await postActionsConnectorExecuteRoute( + mockRouter as unknown as IRouter + ); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.ts b/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.ts new file mode 100644 index 0000000000000..be4468587bdd9 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/post_actions_connector_execute.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 { IRouter } from '@kbn/core/server'; +import { transformError } from '@kbn/securitysolution-es-utils'; + +import { POST_ACTIONS_CONNECTOR_EXECUTE } from '../../common/constants'; +import { + getLangChainMessages, + unsafeGetAssistantMessagesFromRequest, +} from '../lib/langchain/helpers'; +import { buildResponse } from '../lib/build_response'; +import { buildRouteValidation } from '../schemas/common'; +import { + PostActionsConnectorExecuteBody, + PostActionsConnectorExecutePathParams, +} from '../schemas/post_actions_connector_execute'; +import { ElasticAssistantRequestHandlerContext } from '../types'; +import { executeCustomLlmChain } from '../lib/langchain/execute_custom_llm_chain'; + +export const postActionsConnectorExecuteRoute = ( + router: IRouter +) => { + router.post( + { + path: POST_ACTIONS_CONNECTOR_EXECUTE, + validate: { + body: buildRouteValidation(PostActionsConnectorExecuteBody), + params: buildRouteValidation(PostActionsConnectorExecutePathParams), + }, + }, + async (context, request, response) => { + const resp = buildResponse(response); + + try { + const connectorId = decodeURIComponent(request.params.connectorId); + const rawSubActionParamsBody = request.body.params.subActionParams.body; + + // get the actions plugin start contract from the request context: + const actions = (await context.elasticAssistant).actions; + + // get the assistant messages from the request body: + const assistantMessages = unsafeGetAssistantMessagesFromRequest(rawSubActionParamsBody); + + // convert the assistant messages to LangChain messages: + const langChainMessages = getLangChainMessages(assistantMessages); + + const langChainResponseBody = await executeCustomLlmChain({ + actions, + connectorId, + langChainMessages, + request, + }); + + return response.ok({ + body: langChainResponseBody, + }); + } catch (err) { + const error = transformError(err); + + return resp.error({ + body: error.message, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/plugins/elastic_assistant/server/schemas/common.ts b/x-pack/plugins/elastic_assistant/server/schemas/common.ts new file mode 100644 index 0000000000000..00e97a9326c5e --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/schemas/common.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 { fold } from 'fp-ts/lib/Either'; +import { pipe } from 'fp-ts/lib/pipeable'; +import type * as rt from 'io-ts'; +import { exactCheck, formatErrors } from '@kbn/securitysolution-io-ts-utils'; +import type { + RouteValidationFunction, + RouteValidationResultFactory, + RouteValidationError, +} from '@kbn/core/server'; + +type RequestValidationResult = + | { + value: T; + error?: undefined; + } + | { + value?: undefined; + error: RouteValidationError; + }; + +export const buildRouteValidation = + >(schema: T): RouteValidationFunction => + (inputValue: unknown, validationResult: RouteValidationResultFactory) => + pipe( + schema.decode(inputValue), + (decoded) => exactCheck(inputValue, decoded), + fold>( + (errors: rt.Errors) => validationResult.badRequest(formatErrors(errors).join()), + (validatedInput: A) => validationResult.ok(validatedInput) + ) + ); diff --git a/x-pack/plugins/elastic_assistant/server/schemas/post_actions_connector_execute.ts b/x-pack/plugins/elastic_assistant/server/schemas/post_actions_connector_execute.ts new file mode 100644 index 0000000000000..0aae23ed7512d --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/schemas/post_actions_connector_execute.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 * as t from 'io-ts'; + +/** Validates the URL path of a POST request to the `/actions/connector/{connector_id}/_execute` endpoint */ +export const PostActionsConnectorExecutePathParams = t.type({ + connectorId: t.string, +}); + +/** Validates the body of a POST request to the `/actions/connector/{connector_id}/_execute` endpoint */ +export const PostActionsConnectorExecuteBody = t.type({ + params: t.type({ + subActionParams: t.type({ + body: t.string, + }), + subAction: t.string, + }), +}); + +export type PostActionsConnectorExecuteBodyInputs = t.TypeOf< + typeof PostActionsConnectorExecuteBody +>; diff --git a/x-pack/plugins/elastic_assistant/server/types.ts b/x-pack/plugins/elastic_assistant/server/types.ts new file mode 100755 index 0000000000000..cbe7e096b4eb3 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/types.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { + PluginSetupContract as ActionsPluginSetup, + PluginStartContract as ActionsPluginStart, +} from '@kbn/actions-plugin/server'; +import { CustomRequestHandlerContext } from '@kbn/core/server'; + +/** The plugin setup interface */ +export interface ElasticAssistantPluginSetup { + actions: ActionsPluginSetup; +} + +/** The plugin start interface */ +export interface ElasticAssistantPluginStart { + actions: ActionsPluginStart; +} + +export interface ElasticAssistantPluginSetupDependencies { + actions: ActionsPluginSetup; +} +export interface ElasticAssistantPluginStartDependencies { + actions: ActionsPluginStart; +} + +export interface ElasticAssistantApiRequestHandlerContext { + actions: ActionsPluginStart; +} + +/** + * @internal + */ +export type ElasticAssistantRequestHandlerContext = CustomRequestHandlerContext<{ + elasticAssistant: ElasticAssistantApiRequestHandlerContext; +}>; diff --git a/x-pack/plugins/elastic_assistant/tsconfig.json b/x-pack/plugins/elastic_assistant/tsconfig.json new file mode 100644 index 0000000000000..99119202376ec --- /dev/null +++ b/x-pack/plugins/elastic_assistant/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + }, + "include": [ + "common/**/*", + "server/lib/**/*", + "server/**/*", + // must declare *.json explicitly per https://github.com/microsoft/TypeScript/issues/25636 + "server/**/*.json", + "../../../typings/**/*" + ], + "kbn_references": [ + "@kbn/core", + "@kbn/core-http-server", + "@kbn/licensing-plugin", + "@kbn/core-http-request-handler-context-server", + "@kbn/securitysolution-es-utils", + "@kbn/securitysolution-io-ts-utils", + "@kbn/actions-plugin", + "@kbn/elastic-assistant", + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/x-pack/plugins/enterprise_search/common/connectors/connectors.ts b/x-pack/plugins/enterprise_search/common/connectors/connectors.ts index 3ddb425f62686..1fc6c6e7f5c77 100644 --- a/x-pack/plugins/enterprise_search/common/connectors/connectors.ts +++ b/x-pack/plugins/enterprise_search/common/connectors/connectors.ts @@ -30,7 +30,7 @@ export const CONNECTOR_DEFINITIONS: ConnectorServerSideDefinition[] = [ }, { iconPath: 'confluence_cloud.svg', - isBeta: true, + isBeta: false, isNative: true, keywords: ['confluence', 'cloud', 'connector'], name: i18n.translate('xpack.enterpriseSearch.content.nativeConnectors.confluence.name', { @@ -51,7 +51,7 @@ export const CONNECTOR_DEFINITIONS: ConnectorServerSideDefinition[] = [ }, { iconPath: 'jira_cloud.svg', - isBeta: true, + isBeta: false, isNative: true, keywords: ['jira', 'cloud', 'connector'], name: i18n.translate('xpack.enterpriseSearch.content.nativeConnectors.jira.name', { @@ -121,7 +121,7 @@ export const CONNECTOR_DEFINITIONS: ConnectorServerSideDefinition[] = [ }, { iconPath: 'network_drive.svg', - isBeta: true, + isBeta: false, isNative: true, keywords: ['network', 'drive', 'file', 'directory', 'connector'], name: i18n.translate('xpack.enterpriseSearch.content.nativeConnectors.networkDrive.name', { diff --git a/x-pack/plugins/enterprise_search/common/constants.ts b/x-pack/plugins/enterprise_search/common/constants.ts index 14da6aeca4919..8c8ace6fd434f 100644 --- a/x-pack/plugins/enterprise_search/common/constants.ts +++ b/x-pack/plugins/enterprise_search/common/constants.ts @@ -79,7 +79,7 @@ export const ANALYTICS_PLUGIN = { }; export const ELASTICSEARCH_PLUGIN = { - ID: 'elasticsearch', + ID: 'enterpriseSearchElasticsearch', NAME: i18n.translate('xpack.enterpriseSearch.elasticsearch.productName', { defaultMessage: 'Elasticsearch', }), @@ -229,3 +229,4 @@ export const DEFAULT_PRODUCT_FEATURES: ProductFeatures = { }; export const CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX = '.search-acl-filter-'; +export const PLUGIN_ID = 'enterpriseSearch'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/generate_connector_api_key_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/generate_connector_api_key_api_logic.ts index 59145a7721f1a..ace963d9208be 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/generate_connector_api_key_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/generate_connector_api_key_api_logic.ts @@ -8,7 +8,7 @@ import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; -interface ApiKey { +export interface ApiKey { api_key: string; encoded: string; id: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/select_connector/select_connector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/select_connector/select_connector.tsx index 1afc443077e15..ce8cb3c699478 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/select_connector/select_connector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/select_connector/select_connector.tsx @@ -129,7 +129,7 @@ export const SelectConnector: React.FC = () => {

    @@ -150,7 +150,7 @@ export const SelectConnector: React.FC = () => {
    @@ -228,7 +228,7 @@ export const SelectConnector: React.FC = () => { {filteredConnectors.map((connector) => ( { const { openGenerateModal, closeGenerateModal } = useActions(OverviewLogic); const { indexName } = useValues(IndexViewLogic); const { services } = useKibana(); - const { isCloud } = useValues(KibanaLogic); const cloudContext = useCloudDetails(); const codeArgs = { apiKey, + cloudId: cloudContext.cloudId, + indexName, url: cloudContext.elasticsearchUrl || DEFAULT_URL, }; + const assetBasePath = http.basePath.prepend(`/plugins/${PLUGIN_ID}/assets/client_libraries/`); const [selectedLanguage, setSelectedLanguage] = useState(javascriptDefinition); @@ -98,7 +101,6 @@ export const APIGettingStarted = () => { language={language} setSelectedLanguage={setSelectedLanguage} isSelectedLanguage={selectedLanguage === language} - http={http} src={icons[language.id]} /> @@ -106,12 +108,11 @@ export const APIGettingStarted = () => { { />

    - {isCloud - ? i18n.translate( - 'xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.cloudTitle', - { - defaultMessage: 'Store your unique Cloud ID', - } - ) - : i18n.translate( - 'xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.elasticTitle', - { - defaultMessage: 'Store your elasticsearch URL', - } - )} + {i18n.translate( + 'xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.elasticTitle', + { + defaultMessage: 'Store your Elasticsearch URL', + } + )}
    @@ -261,28 +246,24 @@ export const APIGettingStarted = () => { overflow-wrap: anywhere; `} > - {codeArgs.url} + {codeArgs.cloudId + ? dedent`{ + CloudID: "${codeArgs.cloudId}", + Url: "${codeArgs.url}", + }` + : codeArgs.url} } links={[]} - title={ - isCloud - ? i18n.translate( - 'xpack.enterpriseSearch.overview.gettingStarted.cloudId.panelTitleCloud', - { - defaultMessage: 'Copy your Cloud ID', - } - ) - : i18n.translate( - 'xpack.enterpriseSearch.overview.gettingStarted.cloudId.panelTitleElastic', - { - defaultMessage: 'Copy your elasticsearch URL', - } - ) - } + title={i18n.translate( + 'xpack.enterpriseSearch.overview.gettingStarted.cloudId.panelTitleElastic', + { + defaultMessage: 'Copy your Elasticsearch URL', + } + )} overviewPanelProps={{ color: 'plain', hasShadow: false }} /> @@ -290,7 +271,7 @@ export const APIGettingStarted = () => { description={i18n.translate( 'xpack.enterpriseSearch.overview.gettingStarted.configureClient.description', { - defaultMessage: 'Initialize your client with your unique API key and Cloud ID', + defaultMessage: 'Initialize your client with your unique API key', } )} rightPanelContent={ @@ -301,11 +282,10 @@ export const APIGettingStarted = () => { 'configureClient', codeArgs )} - showTryInConsole={showTryInConsole('configureClient')} + consoleRequest={getConsoleRequest('configureClient')} selectedLanguage={selectedLanguage} setSelectedLanguage={setSelectedLanguage} - http={http} - pluginId={''} + assetBasePath={assetBasePath} application={services.application} sharePlugin={services.share} /> @@ -336,11 +316,10 @@ export const APIGettingStarted = () => { 'testConnection', codeArgs )} - showTryInConsole={showTryInConsole('testConnection')} + consoleRequest={getConsoleRequest('testConnection')} selectedLanguage={selectedLanguage} setSelectedLanguage={setSelectedLanguage} - http={http} - pluginId={''} + assetBasePath={assetBasePath} application={services.application} sharePlugin={services.share} /> @@ -365,11 +344,10 @@ export const APIGettingStarted = () => { @@ -397,11 +375,10 @@ export const APIGettingStarted = () => { 'buildSearchQuery', codeArgs )} - showTryInConsole={showTryInConsole('buildSearchQuery')} + consoleRequest={getConsoleRequest('buildSearchQuery')} selectedLanguage={selectedLanguage} setSelectedLanguage={setSelectedLanguage} - http={http} - pluginId={''} + assetBasePath={assetBasePath} application={services.application} sharePlugin={services.share} /> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/curl.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/curl.ts index 4131c42b95fd9..45c67a02798ec 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/curl.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/curl.ts @@ -11,7 +11,7 @@ import { Languages, LanguageDefinition } from '@kbn/search-api-panels'; import { docLinks } from '../../../../../../shared/doc_links'; export const curlDefinition: LanguageDefinition = { - buildSearchQuery: `curl -X POST "\$\{ES_URL\}/books/_search?pretty" \\ + buildSearchQuery: ({ indexName }) => `curl -X POST "\$\{ES_URL\}/${indexName}/_search?pretty" \\ -H "Authorization: ApiKey "\$\{API_KEY\}"" \\ -H "Content-Type: application/json" \\ -d' @@ -33,21 +33,21 @@ export API_KEY="${apiKey}"`, }, iconType: 'curl.svg', id: Languages.CURL, - ingestData: `curl -X POST "\$\{ES_URL\}/_bulk?pretty" \\ + ingestData: ({ indexName }) => `curl -X POST "\$\{ES_URL\}/_bulk?pretty" \\ -H "Authorization: ApiKey "\$\{API_KEY\}"" \\ -H "Content-Type: application/json" \\ -d' -{ "index" : { "_index" : "books" } } +{ "index" : { "_index" : "${indexName}" } } {"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} -{ "index" : { "_index" : "books" } } +{ "index" : { "_index" : "${indexName}" } } {"name": "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585} -{ "index" : { "_index" : "books" } } +{ "index" : { "_index" : "${indexName}" } } {"name": "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328} -{ "index" : { "_index" : "books" } } +{ "index" : { "_index" : "${indexName}" } } {"name": "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227} -{ "index" : { "_index" : "books" } } +{ "index" : { "_index" : "${indexName}" } } {"name": "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} -{ "index" : { "_index" : "books" } } +{ "index" : { "_index" : "${indexName}" } } {"name": "The Handmaid'"'"'s Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311} '`, ingestDataIndex: '', @@ -60,7 +60,7 @@ brew install curl`, defaultMessage: 'cURL', }), languageStyling: 'shell', - testConnection: `curl "\$\{ES_URL\}" \\ + testConnection: ({ indexName }) => `curl "\$\{ES_URL\}/${indexName}" \\ -H "Authorization: ApiKey "\$\{API_KEY\}"" \\ -H "Content-Type: application/json"`, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/go.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/go.ts index 0bb2b99a0682f..fc3d8226f9a0c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/go.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/go.ts @@ -11,31 +11,42 @@ import { Languages, LanguageDefinition } from '@kbn/search-api-panels'; import { docLinks } from '../../../../../../shared/doc_links'; export const goDefinition: LanguageDefinition = { - buildSearchQuery: `searchResp, err := es.Search(). - Index("books"). - Q("snow"). - Do(context.Background()) + buildSearchQuery: ({ indexName }) => `searchResp, err := es.Search( + es.Search.WithContext(context.Background()), + es.Search.WithIndex("${indexName}"), + es.Search.WithQuery("snow"), + es.Search.WithTrackTotalHits(true), + es.Search.WithPretty(), +) fmt.Println(searchResp, err)`, - configureClient: ({ url, apiKey }) => `import ( + configureClient: ({ url, apiKey, cloudId }) => `import ( + "bytes" "context" "fmt" "log" - "strings" -​ - elasticsearch "github.com/elastic/go-elasticsearch/v8" + + "github.com/elastic/go-elasticsearch/v8" ) -func main() { - cfg := elasticsearch.Config{ - Address: "${url}", - APIKey: "${apiKey}", - } - es, err := elasticsearch.NewClient(cfg) - if err != nil { - log.Fatalf("Error creating the client: %s", err) +// ... + +cfg := elasticsearch.Config{ + ${ + cloudId + ? `CloudID:"${cloudId}",` + : `Addresses: []string{ + "${url}", + },` } -}`, + APIKey: "${apiKey}", +} + +es, err := elasticsearch.NewClient(cfg) +if err != nil { + log.Fatalf("Error creating the client: %s", err) +} +`, docLink: docLinks.clientsGoIndex, github: { label: i18n.translate('xpack.enterpriseSearch.languages.go.githubLink', { @@ -45,9 +56,7 @@ func main() { }, iconType: 'go.svg', id: Languages.GO, - ingestData: `ingestResult, err := es.Bulk(). - Index("books"). - Raw(strings.NewReader(\` + ingestData: ({ indexName }) => `buf := bytes.NewBufferString(\` {"index":{"_id":"9780553351927"}} {"name":"Snow Crash","author":"Neal Stephenson","release_date":"1992-06-01","page_count": 470} { "index": { "_id": "9780441017225"}} @@ -59,8 +68,13 @@ func main() { { "index": { "_id": "9780060850524"}} {"name": "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} { "index": { "_id": "9780385490818"}} -{"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311}\n\`)). - Do(context.Background()) +{"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311} +\`) + +ingestResult, err := es.Bulk( + bytes.NewReader(buf.Bytes()), + es.Bulk.WithIndex("${indexName}"), +) fmt.Println(ingestResult, err)`, ingestDataIndex: '', @@ -68,10 +82,11 @@ fmt.Println(ingestResult, err)`, name: i18n.translate('xpack.enterpriseSearch.languages.go', { defaultMessage: 'Go', }), - testConnection: `infores, err := es.Info().Do(context.Background()) - if err != nil { - log.Fatalf("Error getting response: %s", err) - } + testConnection: `// API Key should have cluster monitoring rights +infores, err := es.Info() +if err != nil { + log.Fatalf("Error getting response: %s", err) +} - fmt.Println(infores)`, +fmt.Println(infores)`, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/javascript.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/javascript.ts index 3b636490a495e..c73461a1aa396 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/javascript.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/javascript.ts @@ -11,9 +11,9 @@ import { Languages, LanguageDefinition } from '@kbn/search-api-panels'; import { docLinks } from '../../../../../../shared/doc_links'; export const javascriptDefinition: LanguageDefinition = { - buildSearchQuery: `// Let's search! + buildSearchQuery: ({ indexName }) => `// Let's search! const searchResult = await client.search({ - index: 'my-index-name', + index: '${indexName}', q: '9HY9SWR' }); @@ -35,7 +35,7 @@ const client = new Client({ }, iconType: 'javascript.svg', id: Languages.JAVASCRIPT, - ingestData: `// Sample flight data + ingestData: ({ indexName }) => `// Sample flight data const dataset = [ {'flight': '9HY9SWR', 'price': 841.2656419677076, 'delayed': false}, {'flight': 'X98CCZO', 'price': 882.9826615595518, 'delayed': false}, @@ -46,7 +46,7 @@ const dataset = [ const result = await client.helpers.bulk({ datasource: dataset, onDocument (doc) { - return { index: { _index: 'my-index-name' }}; + return { index: { _index: '${indexName}' }}; } }); @@ -68,7 +68,8 @@ console.log(result); name: i18n.translate('xpack.enterpriseSearch.languages.javascript', { defaultMessage: 'JavaScript', }), - testConnection: `const resp = await client.info(); + testConnection: `// API Key should have cluster monitor rights. +const resp = await client.info(); console.log(resp); /** diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/php.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/php.ts index eec2e50e275dd..51ea055c23ae8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/php.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/php.ts @@ -11,8 +11,8 @@ import { Languages, LanguageDefinition } from '@kbn/search-api-panels'; import { docLinks } from '../../../../../../shared/doc_links'; export const phpDefinition: LanguageDefinition = { - buildSearchQuery: `$params = [ - 'index' => 'books', + buildSearchQuery: ({ indexName }) => `$params = [ + 'index' => '${indexName}', 'body' => [ 'q' => 'snow' ] @@ -33,11 +33,11 @@ print_r($response->asArray());`, }, iconType: 'php.svg', id: Languages.PHP, - ingestData: `$params = [ + ingestData: ({ indexName }) => `$params = [ 'body' => [ [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780553351927', ], ], @@ -49,7 +49,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780441017225', ], ], @@ -61,7 +61,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780451524935', ], ], @@ -73,7 +73,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9781451673319', ], ], @@ -85,7 +85,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780060850524', ], ], @@ -97,7 +97,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780385490818', ], ], @@ -118,7 +118,8 @@ print_r($response->asArray());`, name: i18n.translate('xpack.enterpriseSearch.languages.php', { defaultMessage: 'PHP', }), - testConnection: `$response = $client->info(); + testConnection: `// API Key should have cluster monitor rights. +$response = $client->info(); echo $response->getStatusCode(); echo (string) $response->getBody();`, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/python.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/python.ts index f3fd81b2c1152..79fb811185f18 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/python.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/python.ts @@ -11,7 +11,7 @@ import { Languages, LanguageDefinition } from '@kbn/search-api-panels'; import { docLinks } from '../../../../../../shared/doc_links'; export const pythonDefinition: LanguageDefinition = { - buildSearchQuery: `client.search(index="books", q="snow")`, + buildSearchQuery: ({ indexName }) => `client.search(index="${indexName}", q="snow")`, configureClient: ({ url, apiKey }) => `from elasticsearch import Elasticsearch client = Elasticsearch( @@ -27,18 +27,18 @@ client = Elasticsearch( }, iconType: 'python.svg', id: Languages.PYTHON, - ingestData: `documents = [ - { "index": { "_index": "books", "_id": "9780553351927"}}, + ingestData: ({ indexName }) => `documents = [ + { "index": { "_index": "${indexName}", "_id": "9780553351927"}}, {"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470}, - { "index": { "_index": "books", "_id": "9780441017225"}}, + { "index": { "_index": "${indexName}", "_id": "9780441017225"}}, {"name": "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585}, - { "index": { "_index": "books", "_id": "9780451524935"}}, + { "index": { "_index": "${indexName}", "_id": "9780451524935"}}, {"name": "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328}, - { "index": { "_index": "books", "_id": "9781451673319"}}, + { "index": { "_index": "${indexName}", "_id": "9781451673319"}}, {"name": "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227}, - { "index": { "_index": "books", "_id": "9780060850524"}}, + { "index": { "_index": "${indexName}", "_id": "9780060850524"}}, {"name": "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268}, - { "index": { "_index": "books", "_id": "9780385490818"}}, + { "index": { "_index": "${indexName}", "_id": "9780385490818"}}, {"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311}, ] @@ -52,5 +52,6 @@ client.bulk(operations=documents)`, name: i18n.translate('xpack.enterpriseSearch.languages.python', { defaultMessage: 'Python', }), - testConnection: `client.info()`, + testConnection: `# API key should have cluster monitor rights +client.info()`, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/ruby.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/ruby.ts index 5f67424900d6b..779aa3a99f1fb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/ruby.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/ruby.ts @@ -11,10 +11,10 @@ import { Languages, LanguageDefinition } from '@kbn/search-api-panels'; import { docLinks } from '../../../../../../shared/doc_links'; export const rubyDefinition: LanguageDefinition = { - buildSearchQuery: `client.search(index: 'books', q: 'snow')`, - configureClient: ({ url, apiKey }) => `client = ElasticsearchServerless::Client.new( + buildSearchQuery: ({ indexName }) => `client.search(index: '${indexName}', q: 'snow')`, + configureClient: ({ url, apiKey, cloudId }) => `client = Elasticsearch::Client.new( api_key: '${apiKey}', - url: '${url}' + ${cloudId ? `cloud_id: ${cloudId},` : `url: '${url}',`} ) `, docLink: docLinks.clientsRubyOverview, @@ -26,19 +26,20 @@ export const rubyDefinition: LanguageDefinition = { }, iconType: 'ruby.svg', id: Languages.RUBY, - ingestData: `documents = [ - { index: { _index: 'books', data: {name: "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} } }, - { index: { _index: 'books', data: {name: "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585} } }, - { index: { _index: 'books', data: {name: "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328} } }, - { index: { _index: 'books', data: {name: "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227} } }, - { index: { _index: 'books', data: {name: "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} } }, - { index: { _index: 'books', data: {name: "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311} } } + ingestData: ({ indexName }) => `documents = [ + { index: { _index: '${indexName}', data: {name: "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} } }, + { index: { _index: '${indexName}', data: {name: "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585} } }, + { index: { _index: '${indexName}', data: {name: "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328} } }, + { index: { _index: '${indexName}', data: {name: "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227} } }, + { index: { _index: '${indexName}', data: {name: "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} } }, + { index: { _index: '${indexName}', data: {name: "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311} } } ] client.bulk(body: documents)`, ingestDataIndex: '', - installClient: `$ gem install elasticsearch -v x.x.x`, + installClient: `$ gem install elasticsearch`, name: i18n.translate('xpack.enterpriseSearch.languages.ruby', { defaultMessage: 'Ruby', }), - testConnection: `client.info`, + testConnection: `# API Key should have cluster monitoring rights. +client.info`, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx index 6989f0571efd6..0667451d8e761 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx @@ -28,6 +28,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { ConnectorStatus } from '../../../../../../common/types/connectors'; import { BetaConnectorCallout } from '../../../../shared/beta/beta_connector_callout'; +import { useCloudDetails } from '../../../../shared/cloud_details/cloud_details'; import { docLinks } from '../../../../shared/doc_links'; import { generateEncodedPath } from '../../../../shared/encode_path_params'; import { EuiButtonTo, EuiLinkTo } from '../../../../shared/react_router_helpers'; @@ -45,7 +46,7 @@ import { SearchIndexTabId } from '../search_index'; import { ApiKeyConfig } from './api_key_configuration'; import { ConnectorConfigurationConfig } from './connector_configuration_config'; import { ConnectorNameAndDescription } from './connector_name_and_description/connector_name_and_description'; -import { BETA_CONNECTORS, CONNECTORS } from './constants'; +import { BETA_CONNECTORS, CONNECTORS, getConnectorTemplate } from './constants'; import { NativeConnectorConfiguration } from './native_connector_configuration/native_connector_configuration'; export const ConnectorConfiguration: React.FC = () => { @@ -53,6 +54,8 @@ export const ConnectorConfiguration: React.FC = () => { const { index, recheckIndexLoading } = useValues(IndexViewLogic); const { indexName } = useValues(IndexNameLogic); const { recheckIndex } = useActions(IndexViewLogic); + const cloudContext = useCloudDetails(); + if (!isConnectorIndex(index)) { return <>; } @@ -151,15 +154,14 @@ export const ConnectorConfiguration: React.FC = () => { - {`connectors: - - - connector_id: "${index.connector.id}" - service_type: "${index.connector.service_type || 'changeme'}"${ - apiKeyData?.encoded - ? ` - api_key: "${apiKeyData?.encoded}"` - : '' - }`} + {getConnectorTemplate({ + apiKeyData, + connectorData: { + id: index.connector.id, + service_type: index.connector.service_type, + }, + host: cloudContext.elasticsearchUrl, + })} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/constants.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/constants.ts index b10069f12c3fe..64b4dad084d96 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/constants.ts @@ -5,10 +5,13 @@ * 2.0. */ +import dedent from 'dedent'; + import { CONNECTOR_DEFINITIONS } from '../../../../../../common/connectors/connectors'; import { docLinks } from '../../../../shared/doc_links'; import { CONNECTOR_ICONS } from '../../../../shared/icons/connector_icons'; +import { ApiKey } from '../../../api/connector/generate_connector_api_key_api_logic'; import { ConnectorClientSideDefinition } from './types'; @@ -24,6 +27,7 @@ export const CONNECTORS_DICT: Record = { externalAuthDocsUrl: '', externalDocsUrl: '', icon: CONNECTOR_ICONS.confluence_cloud, + platinumOnly: true, }, custom: { docsUrl: docLinks.connectors, @@ -42,12 +46,14 @@ export const CONNECTORS_DICT: Record = { externalAuthDocsUrl: '', externalDocsUrl: '', icon: CONNECTOR_ICONS.github, + platinumOnly: true, }, gmail: { docsUrl: docLinks.connectorsGmail, externalAuthDocsUrl: '', externalDocsUrl: '', icon: CONNECTOR_ICONS.gmail, + platinumOnly: true, }, google_cloud_storage: { docsUrl: docLinks.connectorsGoogleCloudStorage, @@ -60,12 +66,14 @@ export const CONNECTORS_DICT: Record = { externalAuthDocsUrl: 'https://cloud.google.com/iam/docs/service-account-overview', externalDocsUrl: 'https://developers.google.com/drive', icon: CONNECTOR_ICONS.google_drive, + platinumOnly: true, }, jira: { docsUrl: docLinks.connectorsJira, externalAuthDocsUrl: '', externalDocsUrl: '', icon: CONNECTOR_ICONS.jira_cloud, + platinumOnly: true, }, mongodb: { docsUrl: docLinks.connectorsMongoDB, @@ -90,12 +98,14 @@ export const CONNECTORS_DICT: Record = { externalAuthDocsUrl: '', externalDocsUrl: '', icon: CONNECTOR_ICONS.network_drive, + platinumOnly: true, }, onedrive: { docsUrl: docLinks.connectorsOneDrive, externalAuthDocsUrl: '', externalDocsUrl: '', icon: CONNECTOR_ICONS.onedrive, + platinumOnly: true, }, oracle: { docsUrl: docLinks.connectorsOracle, @@ -121,6 +131,7 @@ export const CONNECTORS_DICT: Record = { externalAuthDocsUrl: '', externalDocsUrl: '', icon: CONNECTOR_ICONS.salesforce, + platinumOnly: true, }, servicenow: { docsUrl: docLinks.connectorsServiceNow, @@ -147,7 +158,7 @@ export const CONNECTORS_DICT: Record = { externalAuthDocsUrl: '', externalDocsUrl: '', icon: CONNECTOR_ICONS.slack, - platinumOnly: false, + platinumOnly: true, }, }; @@ -163,3 +174,29 @@ export const CUSTOM_CONNECTORS = CONNECTORS.filter(({ isNative }) => !isNative); export const NATIVE_CONNECTORS = CONNECTORS.filter(({ isNative }) => isNative); export const BETA_CONNECTORS = CONNECTORS.filter(({ isBeta }) => isBeta); + +export const getConnectorTemplate = ({ + apiKeyData, + connectorData, + host, +}: { + apiKeyData: ApiKey | undefined; + connectorData: { + id: string; + service_type: string | null; + }; + host?: string; +}) => dedent`connectors: + - + connector_id: "${connectorData.id}" + service_type: "${connectorData.service_type || 'changeme'}"${ + apiKeyData?.encoded + ? ` + api_key: "${apiKeyData?.encoded}"` + : '' +} + + elasticsearch: + host: "${host || 'http://localhost:9200'}" + api_key: "${apiKeyData?.encoded || ''}" +`; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/convert_connector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/convert_connector.tsx index d2e009baccc79..bb1669c2c0f65 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/convert_connector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/convert_connector.tsx @@ -46,7 +46,7 @@ export const ConvertConnector: React.FC = () => { {i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.nativeConnector.convertConnector.title', { - defaultMessage: 'Customize your connector', + defaultMessage: 'Self-manage this connector', } )} @@ -57,7 +57,7 @@ export const ConvertConnector: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/elasticsearch_product_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/elasticsearch_product_card.tsx index 3c0609bcf5788..6febf9d072f48 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/elasticsearch_product_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/elasticsearch_product_card.tsx @@ -10,6 +10,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { ELASTICSEARCH_PLUGIN } from '../../../../../common/constants'; +import { docLinks } from '../../../shared/doc_links'; import { ProductCard } from '../product_card'; import { BehavioralAnalyticsProductCard } from './behavioral_analytics_product_card'; @@ -26,6 +27,11 @@ export const ElasticsearchProductCard = () => { icon="logoElasticsearch" name={ELASTICSEARCH_PLUGIN.NAME} productId={ELASTICSEARCH_PLUGIN.ID} + emptyCta + cta={i18n.translate('xpack.enterpriseSearch.elasticsearchCard.cta', { + defaultMessage: 'Learn more', + })} + url={docLinks.elasticsearchGettingStarted} rightPanelItems={[ , , diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/enterprise_search_product_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/enterprise_search_product_card.tsx index b53203aade931..e332d4fad9401 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/enterprise_search_product_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/enterprise_search_product_card.tsx @@ -13,6 +13,7 @@ import { ENTERPRISE_SEARCH_PRODUCT_NAME, ENTERPRISE_SEARCH_CONTENT_PLUGIN, } from '../../../../../common/constants'; +import { docLinks } from '../../../shared/doc_links'; import { ProductCard } from '../product_card'; import { AppSearchProductCard } from './app_search_product_card'; @@ -25,6 +26,10 @@ export const EnterpriseSearchProductCard = () => ( 'Standalone applications tailored to simpler, user-friendly and business-focused search experiences.', })} emptyCta + cta={i18n.translate('xpack.enterpriseSearch.enterpriseSearchCard.cta', { + defaultMessage: 'Learn more', + })} + url={docLinks.start} icon="logoEnterpriseSearch" name={ENTERPRISE_SEARCH_PRODUCT_NAME} productId={ENTERPRISE_SEARCH_CONTENT_PLUGIN.ID} diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts index 779c46907338f..ed6ef8f3886bf 100644 --- a/x-pack/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/plugins/enterprise_search/server/plugin.ts @@ -203,7 +203,7 @@ export class EnterpriseSearchPlugin implements Plugin { diff --git a/x-pack/plugins/event_log/kibana.jsonc b/x-pack/plugins/event_log/kibana.jsonc index 1f05da271664f..ae1da1389b1eb 100644 --- a/x-pack/plugins/event_log/kibana.jsonc +++ b/x-pack/plugins/event_log/kibana.jsonc @@ -11,7 +11,8 @@ "eventLog" ], "optionalPlugins": [ - "spaces" + "spaces", + "serverless" ] } } diff --git a/x-pack/plugins/event_log/server/es/context.mock.ts b/x-pack/plugins/event_log/server/es/context.mock.ts index c974a63a6407f..90514d8f53727 100644 --- a/x-pack/plugins/event_log/server/es/context.mock.ts +++ b/x-pack/plugins/event_log/server/es/context.mock.ts @@ -20,6 +20,7 @@ const createContextMock = () => { } = { logger: loggingSystemMock.createLogger(), esNames: namesMock.create(), + shouldSetExistingAssetsToHidden: true, initialize: jest.fn(), shutdown: jest.fn(), waitTillReady: jest.fn(async () => true), diff --git a/x-pack/plugins/event_log/server/es/context.test.ts b/x-pack/plugins/event_log/server/es/context.test.ts index 681b927478d81..5cb6887af3c9b 100644 --- a/x-pack/plugins/event_log/server/es/context.test.ts +++ b/x-pack/plugins/event_log/server/es/context.test.ts @@ -34,6 +34,7 @@ describe('createEsContext', () => { test('should return is ready state as falsy if not initialized', () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test0', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -48,6 +49,7 @@ describe('createEsContext', () => { test('should return esNames', () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test-index', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -65,6 +67,7 @@ describe('createEsContext', () => { test('should return exist false for esAdapter index template and data stream before initialize', async () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test1', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -86,6 +89,7 @@ describe('createEsContext', () => { test('should return exist true for esAdapter index template and data stream after initialize', async () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test2', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -117,6 +121,7 @@ describe('createEsContext', () => { const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test2', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), @@ -134,6 +139,7 @@ describe('createEsContext', () => { jest.requireMock('./init').initializeEs.mockResolvedValue(false); const context = createEsContext({ logger, + shouldSetExistingAssetsToHidden: true, indexNameRoot: 'test2', kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), diff --git a/x-pack/plugins/event_log/server/es/context.ts b/x-pack/plugins/event_log/server/es/context.ts index c3301e321256e..25d978416e354 100644 --- a/x-pack/plugins/event_log/server/es/context.ts +++ b/x-pack/plugins/event_log/server/es/context.ts @@ -23,6 +23,7 @@ export interface EsContext { waitTillReady(): Promise; readonly initialized: boolean; readonly retryDelay: number; + shouldSetExistingAssetsToHidden: boolean; } export interface EsError { @@ -38,6 +39,7 @@ export interface EsContextCtorParams { logger: Logger; indexNameRoot: string; kibanaVersion: string; + shouldSetExistingAssetsToHidden: boolean; elasticsearchClientPromise: Promise; } @@ -48,6 +50,7 @@ class EsContextImpl implements EsContext { private readonly readySignal: ReadySignal; public initialized: boolean; public readonly retryDelay: number; + public readonly shouldSetExistingAssetsToHidden: boolean; constructor(params: EsContextCtorParams) { this.logger = params.logger; @@ -55,6 +58,7 @@ class EsContextImpl implements EsContext { this.readySignal = createReadySignal(); this.initialized = false; this.retryDelay = RETRY_DELAY; + this.shouldSetExistingAssetsToHidden = params.shouldSetExistingAssetsToHidden; this.esAdapter = new ClusterClientAdapter({ logger: params.logger, elasticsearchClientPromise: params.elasticsearchClientPromise, diff --git a/x-pack/plugins/event_log/server/es/init.test.ts b/x-pack/plugins/event_log/server/es/init.test.ts index 7c81ae80b8823..8cf2b808b8939 100644 --- a/x-pack/plugins/event_log/server/es/init.test.ts +++ b/x-pack/plugins/event_log/server/es/init.test.ts @@ -74,6 +74,12 @@ describe('initializeEs', () => { expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).not.toHaveBeenCalled(); }); + test(`should not read or update existing index templates when specifying shouldSetExistingAssetsToHidden=false`, async () => { + await initializeEs({ ...esContext, shouldSetExistingAssetsToHidden: false }); + expect(esContext.esAdapter.getExistingLegacyIndexTemplates).not.toHaveBeenCalled(); + expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).not.toHaveBeenCalled(); + }); + test(`should continue initialization if getting existing index templates throws an error`, async () => { esContext.esAdapter.getExistingLegacyIndexTemplates.mockRejectedValue(new Error('Fail')); @@ -198,6 +204,12 @@ describe('initializeEs', () => { expect(esContext.esAdapter.setIndexToHidden).not.toHaveBeenCalled(); }); + test(`should not read or update existing index settings when specifying shouldSetExistingAssetsToHidden=false`, async () => { + await initializeEs({ ...esContext, shouldSetExistingAssetsToHidden: false }); + expect(esContext.esAdapter.getExistingIndices).not.toHaveBeenCalled(); + expect(esContext.esAdapter.setIndexToHidden).not.toHaveBeenCalled(); + }); + test(`should continue initialization if getting existing index settings throws an error`, async () => { esContext.esAdapter.getExistingIndices.mockRejectedValue(new Error('Fail')); @@ -287,6 +299,12 @@ describe('initializeEs', () => { expect(esContext.esAdapter.setIndexAliasToHidden).not.toHaveBeenCalled(); }); + test(`should not read or update existing index aliases when specifying shouldSetExistingAssetsToHidden=false`, async () => { + await initializeEs({ ...esContext, shouldSetExistingAssetsToHidden: false }); + expect(esContext.esAdapter.getExistingIndexAliases).not.toHaveBeenCalled(); + expect(esContext.esAdapter.setIndexAliasToHidden).not.toHaveBeenCalled(); + }); + test(`should continue initialization if getting existing index aliases throws an error`, async () => { esContext.esAdapter.getExistingIndexAliases.mockRejectedValue(new Error('Fail')); diff --git a/x-pack/plugins/event_log/server/es/init.ts b/x-pack/plugins/event_log/server/es/init.ts index cf737cbf035c6..b0257f3270a55 100644 --- a/x-pack/plugins/event_log/server/es/init.ts +++ b/x-pack/plugins/event_log/server/es/init.ts @@ -31,8 +31,11 @@ export async function initializeEs(esContext: EsContext): Promise { async function initializeEsResources(esContext: EsContext) { const steps = new EsInitializationSteps(esContext); - // today, setExistingAssetsToHidden() never throws, but just in case ... - await retry(steps.setExistingAssetsToHidden); + // Only set existing assets to hidden if we're not in serverless + if (esContext.shouldSetExistingAssetsToHidden) { + // today, setExistingAssetsToHidden() never throws, but just in case ... + await retry(steps.setExistingAssetsToHidden); + } await retry(steps.createIndexTemplateIfNotExists); await retry(steps.createDataStreamIfNotExists); diff --git a/x-pack/plugins/event_log/server/plugin.test.ts b/x-pack/plugins/event_log/server/plugin.test.ts index fcfd921557645..35e02459010b1 100644 --- a/x-pack/plugins/event_log/server/plugin.test.ts +++ b/x-pack/plugins/event_log/server/plugin.test.ts @@ -18,7 +18,8 @@ describe('event_log plugin', () => { const coreStart = coreMock.createStart() as CoreStart; const plugin = new Plugin(initializerContext); - const setup = plugin.setup(coreSetup); + // serverless setup is currently empty, and there is no mock + const setup = plugin.setup(coreSetup, { serverless: {} }); expect(typeof setup.getLogger).toBe('function'); expect(typeof setup.getProviderActions).toBe('function'); expect(typeof setup.isIndexingEntries).toBe('function'); @@ -40,7 +41,8 @@ describe('event_log plugin', () => { const plugin = new Plugin(initializerContext); const spaces = spacesMock.createStart(); - plugin.setup(coreSetup); + // serverless setup is currently empty, and there is no mock + plugin.setup(coreSetup, { serverless: {} }); plugin.start(coreStart, { spaces }); await plugin.stop(); expect(mockLogger.debug).toBeCalledWith('shutdown: waiting to finish'); diff --git a/x-pack/plugins/event_log/server/plugin.ts b/x-pack/plugins/event_log/server/plugin.ts index 9c96e2ae8073a..7bd9291ab4091 100644 --- a/x-pack/plugins/event_log/server/plugin.ts +++ b/x-pack/plugins/event_log/server/plugin.ts @@ -14,6 +14,7 @@ import { IClusterClient, } from '@kbn/core/server'; import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import { ServerlessPluginSetup } from '@kbn/serverless/server'; import type { IEventLogConfig, @@ -35,6 +36,10 @@ const ACTIONS = { stopping: 'stopping', }; +interface PluginSetupDeps { + serverless?: ServerlessPluginSetup; +} + interface PluginStartDeps { spaces?: SpacesPluginStart; } @@ -56,7 +61,7 @@ export class Plugin implements CorePlugin elasticsearch.client.asInternalUser), kibanaVersion: this.kibanaVersion, + // Only non-serverless deployments may have assets that need to be converted + shouldSetExistingAssetsToHidden: !plugins.serverless, }); this.eventLogService = new EventLogService({ diff --git a/x-pack/plugins/event_log/tsconfig.json b/x-pack/plugins/event_log/tsconfig.json index 4f69e9cce2886..cec36c8f2b785 100644 --- a/x-pack/plugins/event_log/tsconfig.json +++ b/x-pack/plugins/event_log/tsconfig.json @@ -20,6 +20,7 @@ "@kbn/utility-types", "@kbn/std", "@kbn/safer-lodash-set", + "@kbn/serverless", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/exploratory_view/public/application/index.tsx b/x-pack/plugins/exploratory_view/public/application/index.tsx index 83cf16274f9e7..e16565b3a8f36 100644 --- a/x-pack/plugins/exploratory_view/public/application/index.tsx +++ b/x-pack/plugins/exploratory_view/public/application/index.tsx @@ -97,6 +97,7 @@ export const renderApp = ({ diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index b5484c7cd1a15..c05acb3de8b9f 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -383,7 +383,7 @@ export interface RegistryDataStreamRoutingRules { rules: Array<{ target_dataset: string; if: string; - namespace: string; + namespace?: string; }>; } diff --git a/x-pack/plugins/fleet/cypress/e2e/agent_policy.cy.ts b/x-pack/plugins/fleet/cypress/e2e/agent_policy.cy.ts index 63da2cbbfa389..916590c05c0b6 100644 --- a/x-pack/plugins/fleet/cypress/e2e/agent_policy.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/agent_policy.cy.ts @@ -5,7 +5,8 @@ * 2.0. */ import { TOAST_CLOSE_BTN } from '../screens/navigation'; - +import { setupFleetServer } from '../tasks/fleet_server'; +import { AGENT_FLYOUT, AGENT_POLICY_DETAILS_PAGE } from '../screens/fleet'; describe('Edit agent policy', () => { beforeEach(() => { cy.intercept('/api/fleet/agent_policies/policy-1', { @@ -59,4 +60,68 @@ describe('Edit agent policy', () => { expect(interception.request.body.description).to.equal('desc'); }); }); + + it('should show correct fleet server host for custom URL', () => { + setupFleetServer(); + + cy.intercept('/api/fleet/agent_policies/policy-1', { + item: { + id: 'policy-1', + name: 'Agent policy 1', + description: 'desc', + namespace: 'default', + monitoring_enabled: ['logs', 'metrics'], + status: 'active', + fleet_server_host_id: 'fleet-server-1', + package_policies: [], + }, + }); + + const apiKey = { + id: 'key-1', + active: true, + api_key_id: 'PefGQYoB0MXWbqVD6jhr', + api_key: 'this-is-the-api-key', + name: 'key-1', + policy_id: 'policy-1', + created_at: '2023-08-29T14:51:10.473Z', + }; + + cy.intercept('/api/fleet/enrollment_api_keys?**', { + items: [apiKey], + total: 1, + page: 1, + perPage: 10000, + }); + cy.intercept('/api/fleet/enrollment_api_keys/key-1', { + item: apiKey, + }); + cy.intercept('/api/fleet/fleet_server_hosts', { + items: [ + { + id: 'fleet-default-fleet-server-host', + name: 'Default', + is_default: true, + host_urls: ['https://192.168.1.23:8220'], + is_preconfigured: true, + }, + { + id: 'fleet-server-1', + name: 'custom host', + host_urls: ['https://xxx.yyy.zzz:443'], + is_default: false, + is_preconfigured: false, + }, + ], + page: 1, + perPage: 10000, + total: 2, + }); + cy.visit('/app/fleet/policies/policy-1'); + + cy.getBySel(AGENT_POLICY_DETAILS_PAGE.ADD_AGENT_LINK).click(); + cy.getBySel(AGENT_FLYOUT.KUBERNETES_PLATFORM_TYPE).click(); + cy.contains('https://xxx.yyy.zzz:443'); + cy.contains('this-is-the-api-key'); + }); }); diff --git a/x-pack/plugins/fleet/cypress/e2e/integrations_real.cy.ts b/x-pack/plugins/fleet/cypress/e2e/integrations_real.cy.ts index 3e570d0e76f78..c3f7f117f8f36 100644 --- a/x-pack/plugins/fleet/cypress/e2e/integrations_real.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/integrations_real.cy.ts @@ -50,6 +50,28 @@ function setupIntegrations() { cy.wait('@packages'); } +// Infinite scroll +function getAllIntegrations() { + const cardItems = new Set(); + + for (let i = 0; i < 10; i++) { + cy.scrollTo(0, i * 600); + cy.wait(50); + cy.getBySel(INTEGRATION_LIST) + .find('.euiCard') + .each((element) => { + const attrValue = element.attr('data-test-subj'); + if (attrValue) { + cardItems.add(attrValue); + } + }); + } + + return cy.then(() => { + return [...cardItems.values()]; + }); +} + it('should install integration without policy', () => { cy.visit('/app/integrations/detail/tomcat/settings'); @@ -175,10 +197,15 @@ describe('Add Integration - Real API', () => { cy.getBySel(getIntegrationCategories('aws')).click({ scrollBehavior: false }); cy.getBySel(INTEGRATIONS_SEARCHBAR.BADGE).contains('AWS').should('exist'); - cy.getBySel(INTEGRATION_LIST).find('.euiCard').should('have.length.greaterThan', 29); + + getAllIntegrations().then((items) => { + expect(items).to.have.length.greaterThan(29); + }); cy.getBySel(INTEGRATIONS_SEARCHBAR.INPUT).clear().type('Cloud'); - cy.getBySel(INTEGRATION_LIST).find('.euiCard').should('have.length.greaterThan', 3); + getAllIntegrations().then((items) => { + expect(items).to.have.length.greaterThan(3); + }); cy.getBySel(INTEGRATIONS_SEARCHBAR.REMOVE_BADGE_BUTTON).click(); cy.getBySel(INTEGRATIONS_SEARCHBAR.BADGE).should('not.exist'); }); diff --git a/x-pack/plugins/fleet/cypress/e2e/privileges_editor_role.cy.ts b/x-pack/plugins/fleet/cypress/e2e/privileges_editor_role.cy.ts index 1fab19c3f018a..9923b4888b5e3 100644 --- a/x-pack/plugins/fleet/cypress/e2e/privileges_editor_role.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/privileges_editor_role.cy.ts @@ -17,6 +17,7 @@ import { AGENT_FLYOUT, } from '../screens/fleet'; import { ADD_INTEGRATION_POLICY_BTN } from '../screens/integrations'; +import { scrollToIntegration } from '../tasks/integrations'; const usersToCreate = [BuiltInEditorUser]; @@ -57,6 +58,7 @@ describe('When the user has Editor built-in role', () => { describe('Integrations app', () => { it('are visible and can be added', () => { loginWithUserAndWaitForPage(INTEGRATIONS, BuiltInEditorUser); + scrollToIntegration(getIntegrationCard('apache')); cy.getBySel(getIntegrationCard('apache')).click(); cy.getBySel(ADD_INTEGRATION_POLICY_BTN).should('not.be.disabled'); }); diff --git a/x-pack/plugins/fleet/cypress/e2e/privileges_fleet_all_integrations_read.cy.ts b/x-pack/plugins/fleet/cypress/e2e/privileges_fleet_all_integrations_read.cy.ts index 6f1e905e29b63..ae727dbcf7917 100644 --- a/x-pack/plugins/fleet/cypress/e2e/privileges_fleet_all_integrations_read.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/privileges_fleet_all_integrations_read.cy.ts @@ -25,6 +25,7 @@ import { ADD_PACKAGE_POLICY_BTN, } from '../screens/fleet'; import { ADD_INTEGRATION_POLICY_BTN, AGENT_POLICY_NAME_LINK } from '../screens/integrations'; +import { scrollToIntegration } from '../tasks/integrations'; const rolesToCreate = [FleetAllIntegrReadRole]; const usersToCreate = [FleetAllIntegrReadUser]; @@ -81,6 +82,7 @@ describe('When the user has All privilege for Fleet but Read for integrations', describe('Integrations', () => { it('are visible but cannot be added', () => { loginWithUserAndWaitForPage(INTEGRATIONS, FleetAllIntegrReadUser); + scrollToIntegration(getIntegrationCard('apache')); cy.getBySel(getIntegrationCard('apache')).click(); cy.getBySel(ADD_INTEGRATION_POLICY_BTN).should('be.disabled'); }); diff --git a/x-pack/plugins/fleet/cypress/e2e/privileges_fleet_none_integrations_all.cy.ts b/x-pack/plugins/fleet/cypress/e2e/privileges_fleet_none_integrations_all.cy.ts index 71e7d948f928a..535d022dac1f3 100644 --- a/x-pack/plugins/fleet/cypress/e2e/privileges_fleet_none_integrations_all.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/privileges_fleet_none_integrations_all.cy.ts @@ -15,6 +15,7 @@ import { import { loginWithUserAndWaitForPage, logout } from '../tasks/login'; import { ADD_INTEGRATION_POLICY_BTN, getIntegrationCard } from '../screens/integrations'; +import { scrollToIntegration } from '../tasks/integrations'; const rolesToCreate = [FleetNoneIntegrAllRole]; const usersToCreate = [FleetNoneIntegrAllUser]; @@ -34,7 +35,10 @@ describe('When the user has All privileges for Integrations but None for for Fle it('Integrations are visible but cannot be added', () => { loginWithUserAndWaitForPage(INTEGRATIONS, FleetNoneIntegrAllUser); - cy.getBySel(getIntegrationCard('apache')).click(); + + const integrationCardSelector = getIntegrationCard('apache'); + scrollToIntegration(integrationCardSelector); + cy.getBySel(integrationCardSelector).click(); cy.getBySel(ADD_INTEGRATION_POLICY_BTN).should('be.disabled'); }); }); diff --git a/x-pack/plugins/fleet/cypress/e2e/privileges_viewer_role.cy.ts b/x-pack/plugins/fleet/cypress/e2e/privileges_viewer_role.cy.ts index 25a5ea23caf16..89eed6dcb2077 100644 --- a/x-pack/plugins/fleet/cypress/e2e/privileges_viewer_role.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/privileges_viewer_role.cy.ts @@ -13,6 +13,7 @@ import { getIntegrationCard } from '../screens/integrations'; import { MISSING_PRIVILEGES } from '../screens/fleet'; import { ADD_INTEGRATION_POLICY_BTN } from '../screens/integrations'; +import { scrollToIntegration } from '../tasks/integrations'; const usersToCreate = [BuiltInViewerUser]; @@ -44,6 +45,7 @@ describe('When the user has Viewer built-in role', () => { describe('Integrations', () => { it('are visible but cannot be added', () => { loginWithUserAndWaitForPage(INTEGRATIONS, BuiltInViewerUser); + scrollToIntegration(getIntegrationCard('apache')); cy.getBySel(getIntegrationCard('apache')).click(); cy.getBySel(ADD_INTEGRATION_POLICY_BTN).should('be.disabled'); }); diff --git a/x-pack/plugins/fleet/cypress/screens/fleet.ts b/x-pack/plugins/fleet/cypress/screens/fleet.ts index 3b8ffcc63b6f6..af799b6066600 100644 --- a/x-pack/plugins/fleet/cypress/screens/fleet.ts +++ b/x-pack/plugins/fleet/cypress/screens/fleet.ts @@ -88,6 +88,7 @@ export const AGENT_FLYOUT = { MANAGED_TAB: 'managedTab', CONFIRM_AGENT_ENROLLMENT_BUTTON: 'ConfirmAgentEnrollmentButton', INCOMING_DATA_CONFIRMED_CALL_OUT: 'IncomingDataConfirmedCallOut', + KUBERNETES_PLATFORM_TYPE: 'platformTypeKubernetes', }; export const AGENT_POLICIES_CREATE_AGENT_POLICY_FLYOUT = { @@ -228,3 +229,7 @@ export const FLEET_SERVER_SETUP = { export const API_KEYS = { REVOKE_KEY_BUTTON: 'enrollmentTokenTable.revokeBtn', }; + +export const AGENT_POLICY_DETAILS_PAGE = { + ADD_AGENT_LINK: 'addAgentLink', +}; diff --git a/x-pack/plugins/fleet/cypress/tasks/fleet_server.ts b/x-pack/plugins/fleet/cypress/tasks/fleet_server.ts index 8ec8e75c1d13f..2b696f7d7edfb 100644 --- a/x-pack/plugins/fleet/cypress/tasks/fleet_server.ts +++ b/x-pack/plugins/fleet/cypress/tasks/fleet_server.ts @@ -9,22 +9,27 @@ import { createAgentDoc } from './agents'; const FLEET_SERVER_POLICY_ID = 'fleet-server-policy'; // Create a Fleet server policy -export function setupFleetServer() { - let policyId: string; +export async function setupFleetServer() { + const policyId: string = FLEET_SERVER_POLICY_ID; let kibanaVersion: string; cy.request({ method: 'POST', url: '/api/fleet/agent_policies', headers: { 'kbn-xsrf': 'xx' }, + failOnStatusCode: false, body: { id: FLEET_SERVER_POLICY_ID, name: 'Fleet Server policy', namespace: 'default', has_fleet_server: true, }, - }).then((response: any) => { - policyId = response.body.item.id; + }).then((response) => { + // 409 is expected if the policy already exists + // this allows the test to be run repeatedly in dev + if (response.status > 299 && response.status !== 409) { + throw new Error(`Failed to create Fleet Server policy: ${response.body.message}`); + } }); cy.getKibanaVersion().then((version) => { diff --git a/x-pack/plugins/fleet/cypress/tasks/integrations.ts b/x-pack/plugins/fleet/cypress/tasks/integrations.ts index 71a8c3cd2f9a7..cef6322985d06 100644 --- a/x-pack/plugins/fleet/cypress/tasks/integrations.ts +++ b/x-pack/plugins/fleet/cypress/tasks/integrations.ts @@ -9,6 +9,7 @@ import { ADD_INTEGRATION_POLICY_BTN, CREATE_PACKAGE_POLICY_SAVE_BTN, FLYOUT_CLOSE_BTN_SEL, + INTEGRATION_LIST, } from '../screens/integrations'; import { AGENT_POLICY_SYSTEM_MONITORING_CHECKBOX, EXISTING_HOSTS_TAB } from '../screens/fleet'; @@ -68,3 +69,19 @@ export const installPackageWithVersion = (integration: string, version: string) method: 'POST', }); }; + +export function scrollToIntegration(selector: string) { + cy.getBySel(INTEGRATION_LIST); + + return cy.window().then(async (win) => { + let found = false; + let i = 0; + while (!found && i < 10) { + win.scroll(0, i++ * 500); + await new Promise((resolve) => setTimeout(resolve, 200)); + if (win.document.querySelector(`[data-test-subj="${selector}"]`)) { + found = true; + } + } + }); +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/app.tsx b/x-pack/plugins/fleet/public/applications/fleet/app.tsx index d7b8172e70c3e..e7a513e113c4f 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/app.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/app.tsx @@ -255,7 +255,7 @@ export const FleetAppContext: React.FC<{ theme$, fleetStatus, }) => { - const darkModeObservable = useObservable(startServices.theme.theme$); + const darkModeObservable = useObservable(theme$); const isDarkMode = darkModeObservable && darkModeObservable.darkMode; return ( diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/page_steps/install_agent/install_agent_managed.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/page_steps/install_agent/install_agent_managed.tsx index 8b4ff121f3e2a..e78f0407baf91 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/page_steps/install_agent/install_agent_managed.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/page_steps/install_agent/install_agent_managed.tsx @@ -78,6 +78,7 @@ export const InstallElasticAgentManagedPageStep: React.FC selectedApiKeyId: enrollmentAPIKey.id, isComplete: commandCopied || !!enrolledAgentIds.length, fullCopyButton: true, + fleetServerHost: fleetServerHosts?.[0], onCopy: () => setCommandCopied(true), }), ]; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/header/right_content.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/header/right_content.tsx index b07af445532a0..3ec77353fd211 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/header/right_content.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/header/right_content.tsx @@ -69,7 +69,7 @@ export const HeaderRightContent: React.FunctionComponent + {isFleetServerPolicy ? ( } + {...inputs.kafkaPartitionTypeRandomInput.formRowProps} > } + {...inputs.kafkaPartitionTypeRoundRobinInput.formRowProps} > void, output?: Output) { ); const kafkaPartitionTypeRandomInput = useInput( - kafkaOutput?.random?.group_events ? `${kafkaOutput.random.group_events}` : undefined, - undefined, + kafkaOutput?.random?.group_events ? `${kafkaOutput.random.group_events}` : '1', + kafkaPartitionTypeInput.value === kafkaPartitionType.Random + ? validateKafkaPartitioningGroupEvents + : undefined, isDisabled('partition') ); const kafkaPartitionTypeHashInput = useInput( @@ -352,8 +355,10 @@ export function useOutputForm(onSucess: () => void, output?: Output) { isDisabled('partition') ); const kafkaPartitionTypeRoundRobinInput = useInput( - kafkaOutput?.round_robin?.group_events ? `${kafkaOutput.round_robin.group_events}` : undefined, - undefined, + kafkaOutput?.round_robin?.group_events ? `${kafkaOutput.round_robin.group_events}` : '1', + kafkaPartitionTypeInput.value === kafkaPartitionType.RoundRobin + ? validateKafkaPartitioningGroupEvents + : undefined, isDisabled('partition') ); @@ -492,6 +497,8 @@ export function useOutputForm(onSucess: () => void, output?: Output) { const sslCertificateValid = sslCertificateInput.validate(); const sslKeyValid = sslKeyInput.validate(); const diskQueuePathValid = diskQueuePathInput.validate(); + const partitioningRandomGroupEventsValid = kafkaPartitionTypeRandomInput.validate(); + const partitioningRoundRobinGroupEventsValid = kafkaPartitionTypeRoundRobinInput.validate(); if (isLogstash) { // validate logstash @@ -516,7 +523,9 @@ export function useOutputForm(onSucess: () => void, output?: Output) { kafkaDefaultTopicValid && kafkaTopicsValid && additionalYamlConfigValid && - kafkaClientIDValid + kafkaClientIDValid && + partitioningRandomGroupEventsValid && + partitioningRoundRobinGroupEventsValid ); } else { // validate ES @@ -546,6 +555,8 @@ export function useOutputForm(onSucess: () => void, output?: Output) { sslCertificateInput, sslKeyInput, diskQueuePathInput, + kafkaPartitionTypeRandomInput, + kafkaPartitionTypeRoundRobinInput, isLogstash, isKafka, ]); @@ -674,7 +685,8 @@ export function useOutputForm(onSucess: () => void, output?: Output) { : {}), partition: kafkaPartitionTypeInput.value, - ...(kafkaPartitionTypeRandomInput.value + ...(kafkaPartitionTypeInput.value === kafkaPartitionType.Random && + kafkaPartitionTypeRandomInput.value ? { random: { group_events: parseIntegerIfStringDefined( @@ -683,7 +695,8 @@ export function useOutputForm(onSucess: () => void, output?: Output) { }, } : {}), - ...(kafkaPartitionTypeRoundRobinInput.value + ...(kafkaPartitionTypeInput.value === kafkaPartitionType.RoundRobin && + kafkaPartitionTypeRoundRobinInput.value ? { round_robin: { group_events: parseIntegerIfStringDefined( @@ -692,7 +705,8 @@ export function useOutputForm(onSucess: () => void, output?: Output) { }, } : {}), - ...(kafkaPartitionTypeHashInput.value + ...(kafkaPartitionTypeInput.value === kafkaPartitionType.Hash && + kafkaPartitionTypeHashInput.value ? { hash: { hash: kafkaPartitionTypeHashInput.value, diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index 6212a1dffdb7b..83b57093a95c7 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -75,7 +75,9 @@ export const IntegrationsAppContext: React.FC<{ theme$, fleetStatus, }) => { - const isDarkMode = useObservable(startServices.uiSettings.get$('theme:darkMode')); + const theme = useObservable(theme$); + const isDarkMode = theme && theme.darkMode; + const CloudContext = startServices.cloud?.CloudContextProvider || EmptyContext; return ( diff --git a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_local_search.tsx b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_local_search.tsx index 1d640e74b81b1..9df23ce8a8e2a 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_local_search.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_local_search.tsx @@ -13,8 +13,11 @@ import type { IntegrationCardItem } from '../sections/epm/screens/home'; export const searchIdField = 'id'; export const fieldsToSearch = ['name', 'title', 'description']; -export function useLocalSearch(packageList: IntegrationCardItem[]) { +export function useLocalSearch(packageList: IntegrationCardItem[], isLoading: boolean) { const localSearchRef = useRef(new LocalSearch(searchIdField)); + if (isLoading) { + return localSearchRef; + } const localSearch = new LocalSearch(searchIdField); localSearch.indexStrategy = new PrefixIndexStrategy(); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/integration_preference.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/integration_preference.tsx index 4e4aafa271b3b..71f0370d13832 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/integration_preference.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/integration_preference.tsx @@ -160,13 +160,11 @@ export const IntegrationPreference = ({ return ( - {prereleaseIntegrationsEnabled !== undefined && ( - - )} + {title} diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/controls.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/controls.tsx index dbb20ae57caf3..08004cadeb46d 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/controls.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/controls.tsx @@ -5,31 +5,9 @@ * 2.0. */ -import type { ReactNode } from 'react'; -import React, { useCallback } from 'react'; -import { css } from '@emotion/react'; +import React, { type ReactNode } from 'react'; -import { - EuiFlexGrid, - EuiFlexGroup, - EuiFlexItem, - EuiLink, - EuiSpacer, - EuiTitle, - EuiText, -} from '@elastic/eui'; - -import { FormattedMessage } from '@kbn/i18n-react'; - -import { Loading } from '../../../../components'; - -import type { IntegrationCardItem } from '../../screens/home'; - -import type { ExtendedIntegrationCategory } from '../../screens/home/category_facets'; - -import type { IntegrationsURLParameters } from '../../screens/home/hooks/use_available_packages'; - -import { PackageCard } from '../package_card'; +import { EuiFlexGroup, EuiSpacer, EuiTitle } from '@elastic/eui'; interface ControlsColumnProps { controls: ReactNode; @@ -55,111 +33,3 @@ export const ControlsColumn = ({ controls, title }: ControlsColumnProps) => { ); }; - -interface GridColumnProps { - list: IntegrationCardItem[]; - isLoading: boolean; - showMissingIntegrationMessage?: boolean; - showCardLabels?: boolean; -} - -export const GridColumn = ({ - list, - showMissingIntegrationMessage = false, - showCardLabels = false, - isLoading, -}: GridColumnProps) => { - if (isLoading) return ; - - return ( - - {list.length ? ( - list.map((item) => { - return ( - .euiPopover, - & > .euiPopover > .euiPopover__anchor, - & > .euiPopover > .euiPopover__anchor > .euiCard { - height: 100%; - } - `} - > - - - ); - }) - ) : ( - - -

    - {showMissingIntegrationMessage ? ( - - ) : ( - - )} -

    -
    -
    - )} -
    - ); -}; - -interface MissingIntegrationContentProps { - resetQuery: () => void; - setSelectedCategory: (category: ExtendedIntegrationCategory) => void; - setUrlandPushHistory: (params: IntegrationsURLParameters) => void; -} - -export const MissingIntegrationContent = ({ - resetQuery, - setSelectedCategory, - setUrlandPushHistory, -}: MissingIntegrationContentProps) => { - const handleCustomInputsLinkClick = useCallback(() => { - resetQuery(); - setSelectedCategory('custom'); - setUrlandPushHistory({ - categoryId: 'custom', - subCategoryId: '', - }); - }, [resetQuery, setSelectedCategory, setUrlandPushHistory]); - - return ( - -

    - - - - ), - forumLink: ( - - - - ), - }} - /> -

    -
    - ); -}; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/grid.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/grid.tsx new file mode 100644 index 0000000000000..0e85390a4b327 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/grid.tsx @@ -0,0 +1,149 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useRef, useEffect } from 'react'; +import { css } from '@emotion/react'; +import { EuiFlexGrid, EuiFlexItem, EuiSpacer, EuiText, EuiAutoSizer } from '@elastic/eui'; +import { VariableSizeList as List } from 'react-window'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { WindowScroller } from 'react-virtualized'; + +import { Loading } from '../../../../components'; +import type { IntegrationCardItem } from '../../screens/home'; + +import { PackageCard } from '../package_card'; + +interface GridColumnProps { + list: IntegrationCardItem[]; + isLoading: boolean; + showMissingIntegrationMessage?: boolean; + showCardLabels?: boolean; +} + +const VirtualizedRow: React.FC<{ + index: number; + onHeightChange: (index: number, size: number) => void; + style: any; +}> = ({ index, children, style, onHeightChange }) => { + const ref = useRef(null); + + useEffect(() => { + if (ref.current) { + onHeightChange(index, ref.current.clientHeight); + } + }, [index, onHeightChange]); + + return ( +
    +
    + {children} + +
    +
    + ); +}; + +export const GridColumn = ({ + list, + showMissingIntegrationMessage = false, + showCardLabels = false, + isLoading, +}: GridColumnProps) => { + const itemsSizeRefs = useRef(new Map()); + const listRef = useRef(null); + + const onHeightChange = useCallback((index: number, size: number) => { + itemsSizeRefs.current.set(index, size); + if (listRef.current) { + listRef.current.resetAfterIndex(index); + } + }, []); + + if (isLoading) return ; + + if (!list.length) { + return ( + + + +

    + {showMissingIntegrationMessage ? ( + + ) : ( + + )} +

    +
    +
    +
    + ); + } + return ( + <> + { + if (listRef.current) { + listRef.current.scrollTo(scrollTop); + } + }} + > + {() => ( + + {({ width }: { width: number }) => ( + { + const test = itemsSizeRefs.current.get(index) ?? 200; + + return test; + }} + height={window.innerHeight} // plus Don't see an integration message + estimatedItemSize={200} + width={width} + > + {({ index, style }) => { + return ( + + + {list.slice(index * 3, index * 3 + 3).map((item) => { + return ( + .euiPopover, + & > .euiPopover > .euiPopover__anchor, + & > .euiPopover > .euiPopover__anchor > .euiCard { + height: 100%; + } + `} + > + + + ); + })} + + + ); + }} + + )} + + )} + + + ); +}; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/index.tsx index 9f97957b07ef0..97adcaa7e40a6 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/index.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/index.tsx @@ -37,7 +37,9 @@ import { ExperimentalFeaturesService } from '../../../../services'; import { promoteFeaturedIntegrations } from '../utils'; -import { ControlsColumn, MissingIntegrationContent, GridColumn } from './controls'; +import { ControlsColumn } from './controls'; +import { GridColumn } from './grid'; +import { MissingIntegrationContent } from './missing_integrations'; import { SearchBox } from './search_box'; export interface Props { @@ -80,7 +82,7 @@ export const PackageListGrid: FunctionComponent = ({ callout, showCardLabels = true, }) => { - const localSearchRef = useLocalSearch(list); + const localSearchRef = useLocalSearch(list, !!isLoading); const [isPopoverOpen, setPopover] = useState(false); @@ -160,79 +162,88 @@ export const PackageListGrid: FunctionComponent = ({ }, [onSubCategoryClick, selectedSubCategory, splitSubcat?.hiddenSubCategories]); return ( - + - - + + + + {showIntegrationsSubcategories && availableSubCategories?.length ? : null} {showIntegrationsSubcategories ? ( - - {visibleSubCategories?.map((subCategory) => { - const isSelected = subCategory.id === selectedSubCategory; - return ( - - onSubCategoryClick(subCategory.id)} + + + {visibleSubCategories?.map((subCategory) => { + const isSelected = subCategory.id === selectedSubCategory; + return ( + + onSubCategoryClick(subCategory.id)} + > + + + + ); + })} + {hiddenSubCategoriesItems?.length ? ( + + + } + isOpen={isPopoverOpen} + closePopover={closePopover} + panelPaddingSize="none" + anchorPosition="downLeft" > - - + + - ); - })} - {hiddenSubCategoriesItems?.length ? ( - - - } - isOpen={isPopoverOpen} - closePopover={closePopover} - panelPaddingSize="none" - anchorPosition="downLeft" - > - - - - ) : null} - + ) : null} + + ) : null} {callout ? ( <> @@ -241,12 +252,14 @@ export const PackageListGrid: FunctionComponent = ({ ) : null} - + + + {showMissingIntegrationMessage && ( <> diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/missing_integrations.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/missing_integrations.tsx new file mode 100644 index 0000000000000..2156d0a5658f6 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/missing_integrations.tsx @@ -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 React, { useCallback } from 'react'; +import { EuiLink, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import type { ExtendedIntegrationCategory } from '../../screens/home/category_facets'; +import type { IntegrationsURLParameters } from '../../screens/home/hooks/use_available_packages'; + +interface MissingIntegrationContentProps { + resetQuery: () => void; + setSelectedCategory: (category: ExtendedIntegrationCategory) => void; + setUrlandPushHistory: (params: IntegrationsURLParameters) => void; +} + +export const MissingIntegrationContent = ({ + resetQuery, + setSelectedCategory, + setUrlandPushHistory, +}: MissingIntegrationContentProps) => { + const handleCustomInputsLinkClick = useCallback(() => { + resetQuery(); + setSelectedCategory('custom'); + setUrlandPushHistory({ + categoryId: 'custom', + subCategoryId: '', + }); + }, [resetQuery, setSelectedCategory, setUrlandPushHistory]); + + return ( + +

    + + + + ), + forumLink: ( + + + + ), + }} + /> +

    +
    + ); +}; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/search_box.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/search_box.tsx index 593ad3e60e82b..9206de2d48f17 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/search_box.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/search_box.tsx @@ -54,6 +54,24 @@ export const SearchBox: FunctionComponent = ({ }); }; + const onCategoryButtonClick = () => { + if (selectedSubCategory) { + if (setSelectedSubCategory) setSelectedSubCategory(undefined); + setUrlandReplaceHistory({ + categoryId: selectedCategory, + subCategoryId: '', + }); + } else { + setCategory(''); + if (setSelectedSubCategory) setSelectedSubCategory(undefined); + setUrlandReplaceHistory({ + searchString: '', + categoryId: '', + subCategoryId: '', + }); + } + }; + const selectedCategoryTitle = selectedCategory ? categories.find((category) => category.id === selectedCategory)?.title : undefined; @@ -100,15 +118,7 @@ export const SearchBox: FunctionComponent = ({ {getCategoriesLabel}