diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 8f1546099d539..7d83c0851eb8c 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -32,6 +32,7 @@ disabled: - x-pack/plugins/observability_onboarding/e2e/ftr_config_runner.ts - x-pack/plugins/observability_onboarding/e2e/ftr_config.ts - x-pack/test/osquery_cypress/cli_config.ts + - x-pack/test/osquery_cypress/serverless_cli_config.ts - x-pack/test/osquery_cypress/config.ts - x-pack/test/osquery_cypress/visual_config.ts - x-pack/test/security_solution_cypress/cli_config.ts @@ -89,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: @@ -265,6 +269,7 @@ enabled: - x-pack/test/functional_with_es_ssl/apps/cases/group2/config.ts - x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/config.ts - x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/config.ts + - x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/shared/config.ts - x-pack/test/functional/apps/advanced_settings/config.ts - x-pack/test/functional/apps/aiops/config.ts - x-pack/test/functional/apps/api_keys/config.ts @@ -277,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 @@ -311,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 @@ -417,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 068c7d9ab223c..30e7929fd6e19 100644 --- a/.buildkite/pipelines/on_merge_unsupported_ftrs.yml +++ b/.buildkite/pipelines/on_merge_unsupported_ftrs.yml @@ -55,25 +55,21 @@ steps: queue: n2-4-spot depends_on: build timeout_in_minutes: 120 - parallelism: 4 + parallelism: 14 retry: automatic: - - exit_status: '-1' - limit: 3 - exit_status: '*' limit: 1 - command: .buildkite/scripts/steps/functional/security_solution_investigations.sh - label: 'Investigations - Security Solution Tests' + label: 'Investigations - Security Solution Cypress Tests' agents: queue: n2-4-spot depends_on: build timeout_in_minutes: 120 - parallelism: 4 + parallelism: 6 retry: automatic: - - exit_status: '-1' - limit: 3 - exit_status: '*' limit: 1 @@ -86,11 +82,9 @@ steps: parallelism: 2 retry: automatic: - - exit_status: '-1' - limit: 3 - exit_status: '*' limit: 1 - + - command: .buildkite/scripts/steps/functional/defend_workflows.sh label: 'Defend Workflows Cypress Tests' agents: @@ -100,8 +94,6 @@ steps: parallelism: 2 retry: automatic: - - exit_status: '-1' - limit: 3 - exit_status: '*' limit: 1 artifact_paths: @@ -116,8 +108,6 @@ steps: parallelism: 6 retry: automatic: - - exit_status: '-1' - limit: 3 - exit_status: '*' limit: 1 artifact_paths: 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 62950b16bec65..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: 10 - 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,13 +149,28 @@ 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: queue: n2-4-spot depends_on: build timeout_in_minutes: 40 - parallelism: 4 + parallelism: 6 soft_fail: true retry: automatic: 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 9d7c399e87253..c56d94524f60d 100644 --- a/.buildkite/pipelines/pull_request/osquery_cypress.yml +++ b/.buildkite/pipelines/pull_request/osquery_cypress.yml @@ -20,5 +20,22 @@ steps: depends_on: build timeout_in_minutes: 50 soft_fail: true + retry: + 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 bd0c8b2df1749..58b416548ec5f 100644 --- a/.buildkite/pipelines/pull_request/security_solution.yml +++ b/.buildkite/pipelines/pull_request/security_solution.yml @@ -5,13 +5,13 @@ steps: queue: n2-4-spot depends_on: build timeout_in_minutes: 60 - parallelism: 10 + parallelism: 16 retry: automatic: - 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' @@ -33,13 +33,13 @@ steps: queue: n2-4-spot depends_on: build timeout_in_minutes: 120 - parallelism: 4 + parallelism: 6 retry: automatic: - 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/quality-gates/pipeline.tests-production.yaml b/.buildkite/pipelines/quality-gates/pipeline.tests-production.yaml index 483532b9c7435..5a0738ead7d9c 100644 --- a/.buildkite/pipelines/quality-gates/pipeline.tests-production.yaml +++ b/.buildkite/pipelines/quality-gates/pipeline.tests-production.yaml @@ -1,11 +1,6 @@ steps: - - label: ":pipeline::kibana::seedling: Trigger Kibana Tests for ${ENVIRONMENT}" - command: echo "replace me with Kibana specific tests" - agent: - image: "docker.elastic.co/ci-agent-images/basic-buildkite-agent:1688566364" - - - label: ":pipeline::fleet::seedling: Trigger Fleet Kibana Tests for ${ENVIRONMENT}" - command: echo "replace me with Fleet specific Kibana tests" + - label: ":pipeline::fleet::seedling: Trigger Observability Kibana Tests for ${ENVIRONMENT}" + command: echo "replace me with Observability specific Kibana tests" agent: image: "docker.elastic.co/ci-agent-images/basic-buildkite-agent:1688566364" diff --git a/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml b/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml index 483532b9c7435..669b306bc2ceb 100644 --- a/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml +++ b/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml @@ -13,3 +13,8 @@ steps: command: echo "replace me with Security specific Kibana tests" agent: image: "docker.elastic.co/ci-agent-images/basic-buildkite-agent:1688566364" + + - label: ":pipeline::lock::seedling: Trigger Control Plane Kibana Tests for ${ENVIRONMENT}" + command: echo "replace me with Control Plane specific Kibana tests" + agent: + image: "docker.elastic.co/ci-agent-images/basic-buildkite-agent:1688566364" diff --git a/.buildkite/pipelines/quality-gates/pipeline.tests-staging.yaml b/.buildkite/pipelines/quality-gates/pipeline.tests-staging.yaml index 483532b9c7435..5a0738ead7d9c 100644 --- a/.buildkite/pipelines/quality-gates/pipeline.tests-staging.yaml +++ b/.buildkite/pipelines/quality-gates/pipeline.tests-staging.yaml @@ -1,11 +1,6 @@ steps: - - label: ":pipeline::kibana::seedling: Trigger Kibana Tests for ${ENVIRONMENT}" - command: echo "replace me with Kibana specific tests" - agent: - image: "docker.elastic.co/ci-agent-images/basic-buildkite-agent:1688566364" - - - label: ":pipeline::fleet::seedling: Trigger Fleet Kibana Tests for ${ENVIRONMENT}" - command: echo "replace me with Fleet specific Kibana tests" + - label: ":pipeline::fleet::seedling: Trigger Observability Kibana Tests for ${ENVIRONMENT}" + command: echo "replace me with Observability specific Kibana tests" agent: image: "docker.elastic.co/ci-agent-images/basic-buildkite-agent:1688566364" diff --git a/.buildkite/pipelines/serverless.yml b/.buildkite/pipelines/serverless.yml index 08f8cbe2a9ef3..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,8 +60,8 @@ steps: - exit_status: '*' limit: 1 - - command: SERVERLESS_ENVIRONMENT=security .buildkite/scripts/steps/functional/serverless_ftr.sh - label: 'Serverless Security Tests' + - 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 @@ -60,33 +73,31 @@ steps: - exit_status: '*' limit: 1 - - command: .buildkite/scripts/steps/functional/security_serverless.sh - label: 'Serverless Security Cypress Tests' + - command: SERVERLESS_ENVIRONMENT=security .buildkite/scripts/steps/functional/serverless_ftr.sh + label: 'Serverless Security Tests' agents: queue: n2-4-spot depends_on: build timeout_in_minutes: 40 - parallelism: 12 retry: automatic: + - exit_status: '-1' + limit: 3 - exit_status: '*' limit: 1 - artifact_paths: - - "target/kibana-security-serverless/**/*" - - command: .buildkite/scripts/steps/functional/security_serverless.sh - label: 'Explore - Security Solution 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: 12 retry: automatic: + - exit_status: '-1' + limit: 3 - exit_status: '*' limit: 1 - artifact_paths: - - "target/kibana-security-serverless/**/*" - command: .buildkite/scripts/steps/functional/security_serverless.sh label: 'Serverless Security Cypress Tests' @@ -94,7 +105,7 @@ steps: queue: n2-4-spot depends_on: build timeout_in_minutes: 40 - parallelism: 12 + parallelism: 16 retry: automatic: - exit_status: '*' @@ -103,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 @@ -117,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/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts index 5906213d6f5aa..6fe1bb1b251e1 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts @@ -10,6 +10,7 @@ import { execSync } from 'child_process'; import fs from 'fs'; import prConfigs from '../../../pull_requests.json'; import { areChangesSkippable, doAnyChangesMatch } from '#pipeline-utils'; + const prConfig = prConfigs.jobs.find((job) => job.pipelineSlug === 'kibana-pull-request'); if (!prConfig) { @@ -118,6 +119,15 @@ const uploadPipeline = (pipelineContent: string | object) => { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/apm_cypress.yml')); } + if ( + (await doAnyChangesMatch([/^x-pack\/plugins\/observability_onboarding/])) || + GITHUB_PR_LABELS.includes('ci:all-cypress-suites') + ) { + pipeline.push( + getPipeline('.buildkite/pipelines/pull_request/observability_onboarding_cypress.yml') + ); + } + if ( (await doAnyChangesMatch([/^x-pack\/plugins\/profiling/])) || GITHUB_PR_LABELS.includes('ci:all-cypress-suites') diff --git a/.buildkite/scripts/steps/add_gh_labels_to_bk_metadata.ts b/.buildkite/scripts/steps/add_gh_labels_to_bk_metadata.ts index d018786f9397b..71deb29c8f6b8 100644 --- a/.buildkite/scripts/steps/add_gh_labels_to_bk_metadata.ts +++ b/.buildkite/scripts/steps/add_gh_labels_to_bk_metadata.ts @@ -27,15 +27,15 @@ const fetchLabels = (prNumber: PrNumber) => try { const labels = pipe(head, firstMatch, parseInt10, fetchLabels)(`${process.env[parseTarget]}`); - execSync(`buildkite-agent meta-data set gh_labels ${labels}`); - if (alsoAnnotate) - execSync( - `buildkite-agent annotate --context 'default' --style 'info' "Github Labels: ${labels}"` - ); + if (labels) { + execSync(`buildkite-agent meta-data set gh_labels ${labels}`); + if (alsoAnnotate) + execSync( + `buildkite-agent annotate --context 'default' --style 'info' "Github Labels: ${labels}"` + ); + } } catch (e) { - console.error( - `\n!!! Error fetching Github Labels (stringified): \n${JSON.stringify(e, null, 2)}` - ); + console.error(`Error fetching Github Labels for issue ${firstMatch}`); } export {}; 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/apm_cypress.sh b/.buildkite/scripts/steps/functional/apm_cypress.sh index 36b6cb3f1ea2f..55f99a819c076 100755 --- a/.buildkite/scripts/steps/functional/apm_cypress.sh +++ b/.buildkite/scripts/steps/functional/apm_cypress.sh @@ -16,7 +16,7 @@ GH_APM_TEAM_LABEL="Team:APM" if (! is_pr); then echo "--- Add GH labels to buildkite metadata" ts-node .buildkite/scripts/steps/add_gh_labels_to_bk_metadata.ts BUILDKITE_MESSAGE true - GH_ON_MERGE_LABELS="$(buildkite-agent meta-data get gh_labels)" + GH_ON_MERGE_LABELS="$(buildkite-agent meta-data get gh_labels --default '')" fi # Enabling cypress dashboard recording when PR is labeled with `apm:cypress-record` and we are not using the flaky test runner OR on merge with Team:APM label applied 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/defend_workflows.sh b/.buildkite/scripts/steps/functional/defend_workflows.sh index 039d25d2ed8a8..555d6cba2d374 100755 --- a/.buildkite/scripts/steps/functional/defend_workflows.sh +++ b/.buildkite/scripts/steps/functional/defend_workflows.sh @@ -10,4 +10,6 @@ export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} echo "--- Defend Workflows Cypress tests" -yarn --cwd x-pack/plugins/security_solution cypress:dw:run +cd x-pack/plugins/security_solution + +yarn cypress:dw:run; status=$?; yarn junit:merge && exit $status diff --git a/.buildkite/scripts/steps/functional/defend_workflows_vagrant.sh b/.buildkite/scripts/steps/functional/defend_workflows_vagrant.sh index a99cf0e86f4ec..57b7b43163400 100755 --- a/.buildkite/scripts/steps/functional/defend_workflows_vagrant.sh +++ b/.buildkite/scripts/steps/functional/defend_workflows_vagrant.sh @@ -8,7 +8,8 @@ source .buildkite/scripts/steps/functional/common_cypress.sh export JOB=kibana-defend-workflows-endpoint-cypress export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} - echo "--- Defend Workflows Endpoint Cypress tests" -yarn --cwd x-pack/plugins/security_solution cypress:dw:endpoint:run +cd x-pack/plugins/security_solution + +yarn cypress:dw:endpoint:run; status=$?; yarn junit:merge && exit $status diff --git a/.buildkite/scripts/steps/functional/response_ops.sh b/.buildkite/scripts/steps/functional/response_ops.sh index ad603752c1239..1c065b2373b66 100755 --- a/.buildkite/scripts/steps/functional/response_ops.sh +++ b/.buildkite/scripts/steps/functional/response_ops.sh @@ -10,4 +10,6 @@ export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} echo "--- Response Ops Cypress Tests on Security Solution" -yarn --cwd x-pack/test/security_solution_cypress cypress:run:respops:ess +cd x-pack/test/security_solution_cypress + +yarn cypress:run:respops:ess; status=$?; yarn junit:merge && exit $status diff --git a/.buildkite/scripts/steps/functional/response_ops_cases.sh b/.buildkite/scripts/steps/functional/response_ops_cases.sh index 6d4cac8ef4472..52eb3fce1985e 100755 --- a/.buildkite/scripts/steps/functional/response_ops_cases.sh +++ b/.buildkite/scripts/steps/functional/response_ops_cases.sh @@ -10,4 +10,6 @@ export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} echo "--- Response Ops Cases Cypress Tests on Security Solution" -yarn --cwd x-pack/test/security_solution_cypress cypress:run:cases:ess +cd x-pack/test/security_solution_cypress + +yarn cypress:run:cases:ess; status=$?; yarn junit:merge && exit $status diff --git a/.buildkite/scripts/steps/functional/security_serverless.sh b/.buildkite/scripts/steps/functional/security_serverless.sh index 22b40c0f0c963..0a14478414bf3 100644 --- a/.buildkite/scripts/steps/functional/security_serverless.sh +++ b/.buildkite/scripts/steps/functional/security_serverless.sh @@ -10,4 +10,6 @@ export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} echo "--- Security Serverless Cypress Tests" -yarn --cwd x-pack/test/security_solution_cypress cypress:run:serverless +cd x-pack/test/security_solution_cypress + +yarn cypress:run:serverless; status=$?; yarn junit:merge && exit $status diff --git a/.buildkite/scripts/steps/functional/security_serverless_explore.sh b/.buildkite/scripts/steps/functional/security_serverless_explore.sh index a61c49daf130c..805f4fe147180 100644 --- a/.buildkite/scripts/steps/functional/security_serverless_explore.sh +++ b/.buildkite/scripts/steps/functional/security_serverless_explore.sh @@ -10,4 +10,6 @@ export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} echo "--- Explore - Security Solution Cypress Tests" -yarn --cwd x-pack/test/security_solution_cypress cypress:explore:run:serverless +cd x-pack/test/security_solution_cypress + +yarn cypress:explore:run:serverless; status=$?; yarn junit:merge && exit $status diff --git a/.buildkite/scripts/steps/functional/security_serverless_investigations.sh b/.buildkite/scripts/steps/functional/security_serverless_investigations.sh index 57989361049b5..15f249d474c40 100644 --- a/.buildkite/scripts/steps/functional/security_serverless_investigations.sh +++ b/.buildkite/scripts/steps/functional/security_serverless_investigations.sh @@ -10,4 +10,6 @@ export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} echo "--- Investigations Cypress Tests on Serverless" -yarn --cwd x-pack/test/security_solution_cypress cypress:investigations:run:serverless +cd x-pack/test/security_solution_cypress + +yarn cypress:investigations:run:serverless; status=$?; yarn junit:merge && exit $status diff --git a/.buildkite/scripts/steps/functional/security_serverless_osquery.sh b/.buildkite/scripts/steps/functional/security_serverless_osquery.sh new file mode 100755 index 0000000000000..d631424552fa8 --- /dev/null +++ b/.buildkite/scripts/steps/functional/security_serverless_osquery.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/steps/functional/common.sh +source .buildkite/scripts/steps/functional/common_cypress.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 + +echo "--- Security Osquery Serverless Cypress" + +yarn --cwd x-pack/plugins/osquery cypress:serverless:run diff --git a/.buildkite/scripts/steps/functional/security_solution.sh b/.buildkite/scripts/steps/functional/security_solution.sh index fdddc8573cff1..f02419a0b6f8c 100755 --- a/.buildkite/scripts/steps/functional/security_solution.sh +++ b/.buildkite/scripts/steps/functional/security_solution.sh @@ -10,4 +10,6 @@ export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} echo "--- Security Solution Cypress tests (Chrome)" -yarn --cwd x-pack/test/security_solution_cypress cypress:run:ess +cd x-pack/test/security_solution_cypress + +yarn cypress:run:ess; status=$?; yarn junit:merge && exit $status diff --git a/.buildkite/scripts/steps/functional/security_solution_explore.sh b/.buildkite/scripts/steps/functional/security_solution_explore.sh index ff373dd8238e1..e7d21b61f7209 100644 --- a/.buildkite/scripts/steps/functional/security_solution_explore.sh +++ b/.buildkite/scripts/steps/functional/security_solution_explore.sh @@ -10,4 +10,6 @@ export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} echo "--- Explore Cypress Tests on Security Solution" -yarn --cwd x-pack/test/security_solution_cypress cypress:explore:run:ess +cd x-pack/test/security_solution_cypress + +yarn cypress:explore:run:ess; status=$?; yarn junit:merge && exit $status diff --git a/.buildkite/scripts/steps/functional/security_solution_investigations.sh b/.buildkite/scripts/steps/functional/security_solution_investigations.sh index 5e7bcf9aa550e..217e79bc9ecfc 100644 --- a/.buildkite/scripts/steps/functional/security_solution_investigations.sh +++ b/.buildkite/scripts/steps/functional/security_solution_investigations.sh @@ -10,4 +10,6 @@ export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} echo "--- Investigations - Security Solution Cypress Tests" -yarn --cwd x-pack/test/security_solution_cypress cypress:investigations:run:ess +cd x-pack/test/security_solution_cypress + +yarn cypress:investigations:run:ess; status=$?; yarn junit:merge && exit $status 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 eecffc061f483..cd4fe15e8827c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -70,7 +70,7 @@ packages/kbn-cli-dev-mode @elastic/kibana-operations x-pack/plugins/cloud_integrations/cloud_chat @elastic/kibana-core x-pack/plugins/cloud_integrations/cloud_chat_provider @elastic/kibana-core x-pack/plugins/cloud_integrations/cloud_data_migration @elastic/platform-onboarding -x-pack/plugins/cloud_defend @elastic/sec-cloudnative-integrations +x-pack/plugins/cloud_defend @elastic/kibana-cloud-security-posture x-pack/plugins/cloud_integrations/cloud_experiments @elastic/kibana-core x-pack/plugins/cloud_integrations/cloud_full_story @elastic/kibana-core x-pack/plugins/cloud_integrations/cloud_gain_sight @elastic/kibana-core @@ -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 @@ -459,7 +459,7 @@ src/plugins/kibana_overview @elastic/appex-sharedux src/plugins/kibana_react @elastic/appex-sharedux src/plugins/kibana_usage_collection @elastic/kibana-core src/plugins/kibana_utils @elastic/kibana-app-services -x-pack/plugins/kubernetes_security @elastic/sec-cloudnative-integrations +x-pack/plugins/kubernetes_security @elastic/kibana-cloud-security-posture packages/kbn-language-documentation-popover @elastic/kibana-visualizations packages/kbn-lens-embeddable-utils @elastic/infra-monitoring-ui x-pack/plugins/lens @elastic/kibana-visualizations @@ -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 @@ -595,15 +599,17 @@ packages/kbn-search-api-panels @elastic/enterprise-search-frontend examples/search_examples @elastic/kibana-data-discovery packages/kbn-search-response-warnings @elastic/kibana-data-discovery x-pack/plugins/searchprofiler @elastic/platform-deployment-management -x-pack/test/security_api_integration/packages/helpers @elastic/kibana-core +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 x-pack/plugins/security_solution_serverless @elastic/security-solution x-pack/packages/security-solution/side_nav @elastic/security-threat-hunting-explore x-pack/packages/security-solution/storybook/config @elastic/security-threat-hunting-explore +x-pack/packages/security-solution/upselling @elastic/security-threat-hunting-explore x-pack/test/security_functional/plugins/test_endpoints @elastic/kibana-security packages/kbn-securitysolution-autocomplete @elastic/security-detection-engine x-pack/packages/security-solution/data_table @elastic/security-threat-hunting-investigations @@ -632,7 +638,7 @@ x-pack/plugins/serverless_search @elastic/enterprise-search-frontend packages/serverless/storybook/config @elastic/appex-sharedux packages/serverless/types @elastic/appex-sharedux test/plugin_functional/plugins/session_notifications @elastic/kibana-core -x-pack/plugins/session_view @elastic/sec-cloudnative-integrations +x-pack/plugins/session_view @elastic/kibana-cloud-security-posture packages/kbn-set-map @elastic/kibana-operations examples/share_examples @elastic/kibana-app-services src/plugins/share @elastic/appex-sharedux @@ -745,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 @@ -823,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 @@ -1034,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 @@ -1277,6 +1301,7 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management @elastic/security-defend-workflows /x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management @elastic/security-defend-workflows /x-pack/plugins/security_solution_serverless/public/upselling/sections/endpoint_management @elastic/security-defend-workflows +/x-pack/plugins/security_solution_serverless/server/endpoint @elastic/security-defend-workflows ## Security Solution sub teams - security-telemetry (Data Engineering) x-pack/plugins/security_solution/server/usage/ @elastic/security-data-analytics @@ -1289,6 +1314,7 @@ x-pack/test/security_solution_cypress/cli_config.ts @elastic/security-engineerin x-pack/test/security_solution_cypress/config.ts @elastic/security-engineering-productivity x-pack/test/security_solution_cypress/runner.ts @elastic/security-engineering-productivity x-pack/test/security_solution_cypress/serverless_config.ts @elastic/security-engineering-productivity +x-pack/test/security_solution_cypress/cypress/tags.ts @elastic/security-engineering-productivity ## Security Solution sub teams - adaptive-workload-protection x-pack/plugins/security_solution/public/common/components/sessions_viewer @elastic/kibana-cloud-security-posture 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 3c2653e17a1a1..ab2fd467cd958 100644 --- a/api_docs/actions.devdocs.json +++ b/api_docs/actions.devdocs.json @@ -2311,124 +2311,6 @@ } ], "interfaces": [ - { - "parentPluginId": "actions", - "id": "def-server.ActionResult", - "type": "Interface", - "tags": [], - "label": "ActionResult", - "description": [], - "signature": [ - { - "pluginId": "actions", - "scope": "server", - "docId": "kibActionsPluginApi", - "section": "def-server.ActionResult", - "text": "ActionResult" - }, - "" - ], - "path": "x-pack/plugins/actions/server/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "actions", - "id": "def-server.ActionResult.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/actions/server/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "actions", - "id": "def-server.ActionResult.actionTypeId", - "type": "string", - "tags": [], - "label": "actionTypeId", - "description": [], - "path": "x-pack/plugins/actions/server/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "actions", - "id": "def-server.ActionResult.name", - "type": "string", - "tags": [], - "label": "name", - "description": [], - "path": "x-pack/plugins/actions/server/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "actions", - "id": "def-server.ActionResult.isMissingSecrets", - "type": "CompoundType", - "tags": [], - "label": "isMissingSecrets", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "x-pack/plugins/actions/server/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "actions", - "id": "def-server.ActionResult.config", - "type": "Uncategorized", - "tags": [], - "label": "config", - "description": [], - "signature": [ - "Config | undefined" - ], - "path": "x-pack/plugins/actions/server/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "actions", - "id": "def-server.ActionResult.isPreconfigured", - "type": "boolean", - "tags": [], - "label": "isPreconfigured", - "description": [], - "path": "x-pack/plugins/actions/server/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "actions", - "id": "def-server.ActionResult.isDeprecated", - "type": "boolean", - "tags": [], - "label": "isDeprecated", - "description": [], - "path": "x-pack/plugins/actions/server/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "actions", - "id": "def-server.ActionResult.isSystemAction", - "type": "boolean", - "tags": [], - "label": "isSystemAction", - "description": [], - "path": "x-pack/plugins/actions/server/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "actions", "id": "def-server.ActionsApiRequestHandlerContext", @@ -2967,43 +2849,37 @@ }, { "parentPluginId": "actions", - "id": "def-server.FindActionResult", + "id": "def-server.FindConnectorResult", "type": "Interface", "tags": [], - "label": "FindActionResult", + "label": "FindConnectorResult", "description": [], "signature": [ { "pluginId": "actions", "scope": "server", "docId": "kibActionsPluginApi", - "section": "def-server.FindActionResult", - "text": "FindActionResult" + "section": "def-server.FindConnectorResult", + "text": "FindConnectorResult" }, " extends ", - { - "pluginId": "actions", - "scope": "server", - "docId": "kibActionsPluginApi", - "section": "def-server.ActionResult", - "text": "ActionResult" - }, + "Connector", "<", "ActionTypeConfig", ">" ], - "path": "x-pack/plugins/actions/server/types.ts", + "path": "x-pack/plugins/actions/server/application/connector/types/connector.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "actions", - "id": "def-server.FindActionResult.referencedByCount", + "id": "def-server.FindConnectorResult.referencedByCount", "type": "number", "tags": [], "label": "referencedByCount", "description": [], - "path": "x-pack/plugins/actions/server/types.ts", + "path": "x-pack/plugins/actions/server/application/connector/types/connector.ts", "deprecated": false, "trackAdoption": false } @@ -3268,6 +3144,22 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "actions", + "id": "def-server.ActionResult", + "type": "Type", + "tags": [], + "label": "ActionResult", + "description": [], + "signature": [ + "Connector", + "" + ], + "path": "x-pack/plugins/actions/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "actions", "id": "def-server.ActionsAuthorization", @@ -3325,13 +3217,13 @@ }, "<", "ActionTypeConfig", - ">>; getAll: ({ includeSystemActions }?: GetAllOptions) => Promise<", + ">>; getAll: ({ includeSystemActions }?: { includeSystemActions?: boolean | undefined; }) => Promise<", { "pluginId": "actions", "scope": "server", "docId": "kibActionsPluginApi", - "section": "def-server.FindActionResult", - "text": "FindActionResult" + "section": "def-server.FindConnectorResult", + "text": "FindConnectorResult" }, "[]>; getBulk: ({ ids, throwIfSystemAction, }: { ids: string[]; throwIfSystemAction?: boolean | undefined; }) => Promise<", { @@ -3355,9 +3247,7 @@ "section": "def-common.ActionTypeExecutorResult", "text": "ActionTypeExecutorResult" }, - ">; enqueueExecution: (options: ", - "ExecuteOptions", - ") => Promise; bulkEnqueueExecution: (options: ", + ">; bulkEnqueueExecution: (options: ", "ExecuteOptions", "[]) => Promise; ephemeralEnqueuedExecution: (options: ", "ExecuteOptions", @@ -3369,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", @@ -5545,13 +5431,10 @@ { "parentPluginId": "actions", "id": "def-common.AlertingConnectorFeature.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false @@ -5559,13 +5442,10 @@ { "parentPluginId": "actions", "id": "def-common.AlertingConnectorFeature.compatibility", - "type": "Any", + "type": "string", "tags": [], "label": "compatibility", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false @@ -5598,13 +5478,10 @@ { "parentPluginId": "actions", "id": "def-common.CasesConnectorFeature.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false @@ -5612,13 +5489,10 @@ { "parentPluginId": "actions", "id": "def-common.CasesConnectorFeature.compatibility", - "type": "Any", + "type": "string", "tags": [], "label": "compatibility", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false @@ -5724,13 +5598,10 @@ { "parentPluginId": "actions", "id": "def-common.GeneralFeature.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false @@ -5738,13 +5609,10 @@ { "parentPluginId": "actions", "id": "def-common.GeneralFeature.compatibility", - "type": "Any", + "type": "string", "tags": [], "label": "compatibility", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false @@ -5792,13 +5660,10 @@ { "parentPluginId": "actions", "id": "def-common.SecuritySolutionFeature.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false @@ -5806,13 +5671,10 @@ { "parentPluginId": "actions", "id": "def-common.SecuritySolutionFeature.compatibility", - "type": "Any", + "type": "string", "tags": [], "label": "compatibility", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false @@ -5845,13 +5707,10 @@ { "parentPluginId": "actions", "id": "def-common.UptimeConnectorFeature.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false @@ -5859,13 +5718,10 @@ { "parentPluginId": "actions", "id": "def-common.UptimeConnectorFeature.compatibility", - "type": "Any", + "type": "string", "tags": [], "label": "compatibility", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/actions/common/connector_feature_config.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 25f69e85c5a24..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 275 | 10 | 269 | 27 | +| 267 | 0 | 261 | 30 | ## Client diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 097a62a9fbb31..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.devdocs.json b/api_docs/aiops.devdocs.json index a5d2c0392ddfb..7d557f4d3c601 100644 --- a/api_docs/aiops.devdocs.json +++ b/api_docs/aiops.devdocs.json @@ -550,6 +550,28 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "aiops", + "id": "def-public.AiopsAppDependencies.i18n", + "type": "Object", + "tags": [], + "label": "i18n", + "description": [ + "\nInternationalisation service" + ], + "signature": [ + { + "pluginId": "@kbn/core-i18n-browser", + "scope": "common", + "docId": "kibKbnCoreI18nBrowserPluginApi", + "section": "def-common.I18nStart", + "text": "I18nStart" + } + ], + "path": "x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "aiops", "id": "def-public.AiopsAppDependencies.fieldStats", diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 941637122e531..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 60 | 1 | 3 | 0 | +| 61 | 1 | 3 | 0 | ## Client diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index 1804e89ca9334..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<", { @@ -4692,7 +4871,7 @@ "MuteOptions", ") => Promise; unmuteInstance: (options: ", "MuteOptions", - ") => Promise; runSoon: (options: { id: string; }) => Promise; listRuleTypes: () => Promise Promise; runSoon: (options: { id: string; }) => Promise; listRuleTypes: () => Promise>; getSpaceId: () => string | undefined; getAuthorization: () => ", { @@ -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 51c1b5e833cde..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-22 +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 4e0efa8b4f074..e1b038257f9bf 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -263,21 +263,9 @@ "APMPluginSetupDependencies", ") => { config$: ", "Observable", - "; enabled: boolean; autoCreateApmDataView: boolean; serviceMapEnabled: boolean; serviceMapFingerprintBucketSize: number; serviceMapFingerprintGlobalBucketSize: number; serviceMapTraceIdBucketSize: number; serviceMapTraceIdGlobalBucketSize: number; serviceMapMaxTracesPerRequest: number; serviceMapTerminateAfter: number; serviceMapMaxTraces: number; ui: Readonly<{} & { enabled: boolean; maxTraceItems: number; }>; searchAggregatedTransactions: ", + "; searchAggregatedTransactions: ", "SearchAggregatedTransactionSetting", - "; telemetryCollectionEnabled: boolean; metricsInterval: number; agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; forceSyntheticSource: boolean; latestAgentVersionsUrl: string; serverlessOnboarding: boolean; serverless: Readonly<{} & { enabled: true; }>; managedServiceUrl: string; featureFlags: Readonly<{} & { agentConfigurationAvailable: boolean; configurableIndicesAvailable: boolean; infrastructureTabAvailable: boolean; infraUiAvailable: boolean; migrationToFleetAvailable: boolean; sourcemapApiAvailable: boolean; storageExplorerAvailable: boolean; }>; }>>; getApmIndices: () => Promise>; createApmEventClient: ({ request, context, debug, }: { debug?: boolean | undefined; request: ", - { - "pluginId": "@kbn/core-http-server", - "scope": "common", - "docId": "kibKbnCoreHttpServerPluginApi", - "section": "def-common.KibanaRequest", - "text": "KibanaRequest" - }, - "; context: ", - "ApmPluginRequestHandlerContext", - "; }) => Promise<", - "APMEventClient", - ">; }" + "; telemetryCollectionEnabled: boolean; metricsInterval: number; agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; forceSyntheticSource: boolean; latestAgentVersionsUrl: string; serverless: Readonly<{} & { enabled: true; }>; serverlessOnboarding: boolean; managedServiceUrl: string; featureFlags: Readonly<{} & { agentConfigurationAvailable: boolean; configurableIndicesAvailable: boolean; infrastructureTabAvailable: boolean; infraUiAvailable: boolean; migrationToFleetAvailable: boolean; sourcemapApiAvailable: boolean; storageExplorerAvailable: boolean; }>; }>>; }" ], "path": "x-pack/plugins/apm/server/plugin.ts", "deprecated": false, @@ -409,518 +397,7 @@ } ], "functions": [], - "interfaces": [ - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources", - "type": "Interface", - "tags": [], - "label": "APMRouteHandlerResources", - "description": [], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.request", - "type": "Object", - "tags": [], - "label": "request", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-server", - "scope": "common", - "docId": "kibKbnCoreHttpServerPluginApi", - "section": "def-common.KibanaRequest", - "text": "KibanaRequest" - }, - "" - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.context", - "type": "CompoundType", - "tags": [], - "label": "context", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-request-handler-context-server", - "scope": "common", - "docId": "kibKbnCoreHttpRequestHandlerContextServerPluginApi", - "section": "def-common.RequestHandlerContext", - "text": "RequestHandlerContext" - }, - " & { licensing: Promise<", - { - "pluginId": "licensing", - "scope": "server", - "docId": "kibLicensingPluginApi", - "section": "def-server.LicensingApiRequestHandlerContext", - "text": "LicensingApiRequestHandlerContext" - }, - ">; alerting: Promise<", - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.AlertingApiRequestHandlerContext", - "text": "AlertingApiRequestHandlerContext" - }, - ">; rac: Promise<", - { - "pluginId": "ruleRegistry", - "scope": "server", - "docId": "kibRuleRegistryPluginApi", - "section": "def-server.RacApiRequestHandlerContext", - "text": "RacApiRequestHandlerContext" - }, - ">; }" - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.params", - "type": "Object", - "tags": [], - "label": "params", - "description": [], - "signature": [ - "{ query: { _inspect: boolean; }; }" - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.config", - "type": "Object", - "tags": [], - "label": "config", - "description": [], - "signature": [ - "{ readonly indices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; }>; readonly enabled: boolean; readonly autoCreateApmDataView: boolean; readonly serviceMapEnabled: boolean; readonly serviceMapFingerprintBucketSize: number; readonly serviceMapFingerprintGlobalBucketSize: number; readonly serviceMapTraceIdBucketSize: number; readonly serviceMapTraceIdGlobalBucketSize: number; readonly serviceMapMaxTracesPerRequest: number; readonly serviceMapTerminateAfter: number; readonly serviceMapMaxTraces: number; readonly ui: Readonly<{} & { enabled: boolean; maxTraceItems: number; }>; readonly searchAggregatedTransactions: ", - "SearchAggregatedTransactionSetting", - "; readonly telemetryCollectionEnabled: boolean; readonly metricsInterval: number; readonly agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; readonly forceSyntheticSource: boolean; readonly latestAgentVersionsUrl: string; readonly serverlessOnboarding: boolean; readonly serverless: Readonly<{} & { enabled: true; }>; readonly managedServiceUrl: string; readonly featureFlags: Readonly<{} & { agentConfigurationAvailable: boolean; configurableIndicesAvailable: boolean; infrastructureTabAvailable: boolean; infraUiAvailable: boolean; migrationToFleetAvailable: boolean; sourcemapApiAvailable: boolean; storageExplorerAvailable: boolean; }>; }" - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.featureFlags", - "type": "Object", - "tags": [], - "label": "featureFlags", - "description": [], - "signature": [ - "{ agentConfigurationAvailable: boolean; configurableIndicesAvailable: boolean; infrastructureTabAvailable: boolean; infraUiAvailable: boolean; migrationToFleetAvailable: boolean; sourcemapApiAvailable: boolean; storageExplorerAvailable: boolean; }" - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.logger", - "type": "Object", - "tags": [], - "label": "logger", - "description": [], - "signature": [ - { - "pluginId": "@kbn/logging", - "scope": "common", - "docId": "kibKbnLoggingPluginApi", - "section": "def-common.Logger", - "text": "Logger" - } - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.core", - "type": "Object", - "tags": [], - "label": "core", - "description": [], - "signature": [ - "APMCore" - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.plugins", - "type": "Object", - "tags": [], - "label": "plugins", - "description": [], - "signature": [ - "{ data: { setup: ", - { - "pluginId": "data", - "scope": "server", - "docId": "kibDataPluginApi", - "section": "def-server.DataPluginSetup", - "text": "DataPluginSetup" - }, - "; start: () => Promise<", - { - "pluginId": "data", - "scope": "server", - "docId": "kibDataPluginApi", - "section": "def-server.DataPluginStart", - "text": "DataPluginStart" - }, - ">; }; features: { setup: ", - { - "pluginId": "features", - "scope": "server", - "docId": "kibFeaturesPluginApi", - "section": "def-server.PluginSetupContract", - "text": "PluginSetupContract" - }, - "; start: () => Promise<", - { - "pluginId": "features", - "scope": "server", - "docId": "kibFeaturesPluginApi", - "section": "def-server.PluginStartContract", - "text": "PluginStartContract" - }, - ">; }; licensing: { setup: ", - { - "pluginId": "licensing", - "scope": "server", - "docId": "kibLicensingPluginApi", - "section": "def-server.LicensingPluginSetup", - "text": "LicensingPluginSetup" - }, - "; start: () => Promise<", - { - "pluginId": "licensing", - "scope": "server", - "docId": "kibLicensingPluginApi", - "section": "def-server.LicensingPluginStart", - "text": "LicensingPluginStart" - }, - ">; }; observability: { setup: { getAlertDetailsConfig(): Readonly<{} & { uptime: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; observability: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; }>; getScopedAnnotationsClient: (requestContext: ", - { - "pluginId": "@kbn/core-http-request-handler-context-server", - "scope": "common", - "docId": "kibKbnCoreHttpRequestHandlerContextServerPluginApi", - "section": "def-common.RequestHandlerContext", - "text": "RequestHandlerContext" - }, - " & { licensing: Promise<", - { - "pluginId": "licensing", - "scope": "server", - "docId": "kibLicensingPluginApi", - "section": "def-server.LicensingApiRequestHandlerContext", - "text": "LicensingApiRequestHandlerContext" - }, - ">; }, request: ", - { - "pluginId": "@kbn/core-http-server", - "scope": "common", - "docId": "kibKbnCoreHttpServerPluginApi", - "section": "def-common.KibanaRequest", - "text": "KibanaRequest" - }, - ") => Promise<{ readonly index: string; create: (createParams: { annotation: { type: string; }; '@timestamp': string; message: string; } & { tags?: string[] | undefined; service?: { name?: string | undefined; environment?: string | undefined; version?: string | undefined; } | undefined; }) => Promise<{ _id: string; _index: string; _source: ", - "Annotation", - "; }>; getById: (getByIdParams: { id: string; }) => Promise<", - "GetResponse", - ">; delete: (deleteParams: { id: string; }) => Promise<", - "WriteResponseBase", - ">; } | undefined>; alertsLocator: ", - { - "pluginId": "share", - "scope": "common", - "docId": "kibSharePluginApi", - "section": "def-common.LocatorPublic", - "text": "LocatorPublic" - }, - "<", - { - "pluginId": "observability", - "scope": "common", - "docId": "kibObservabilityPluginApi", - "section": "def-common.AlertsLocatorParams", - "text": "AlertsLocatorParams" - }, - ">; }; start: () => Promise; }; ruleRegistry: { setup: ", - { - "pluginId": "ruleRegistry", - "scope": "server", - "docId": "kibRuleRegistryPluginApi", - "section": "def-server.RuleRegistryPluginSetupContract", - "text": "RuleRegistryPluginSetupContract" - }, - "; start: () => Promise<", - { - "pluginId": "ruleRegistry", - "scope": "server", - "docId": "kibRuleRegistryPluginApi", - "section": "def-server.RuleRegistryPluginStartContract", - "text": "RuleRegistryPluginStartContract" - }, - ">; }; infra: { setup: ", - { - "pluginId": "infra", - "scope": "server", - "docId": "kibInfraPluginApi", - "section": "def-server.InfraPluginSetup", - "text": "InfraPluginSetup" - }, - "; start: () => Promise<", - { - "pluginId": "infra", - "scope": "server", - "docId": "kibInfraPluginApi", - "section": "def-server.InfraPluginStart", - "text": "InfraPluginStart" - }, - ">; }; dataViews: { setup: {}; start: () => Promise<", - { - "pluginId": "dataViews", - "scope": "server", - "docId": "kibDataViewsPluginApi", - "section": "def-server.DataViewsServerPluginStart", - "text": "DataViewsServerPluginStart" - }, - ">; }; share: { setup: ", - { - "pluginId": "share", - "scope": "server", - "docId": "kibSharePluginApi", - "section": "def-server.SharePluginSetup", - "text": "SharePluginSetup" - }, - "; start: () => Promise; }; actions?: { setup: ", - { - "pluginId": "actions", - "scope": "server", - "docId": "kibActionsPluginApi", - "section": "def-server.PluginSetupContract", - "text": "PluginSetupContract" - }, - "; start: () => Promise<", - { - "pluginId": "actions", - "scope": "server", - "docId": "kibActionsPluginApi", - "section": "def-server.PluginStartContract", - "text": "PluginStartContract" - }, - ">; } | undefined; alerting?: { setup: ", - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.PluginSetupContract", - "text": "PluginSetupContract" - }, - "; start: () => Promise<", - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.PluginStartContract", - "text": "PluginStartContract" - }, - ">; } | undefined; cloud?: { setup: ", - { - "pluginId": "cloud", - "scope": "server", - "docId": "kibCloudPluginApi", - "section": "def-server.CloudSetup", - "text": "CloudSetup" - }, - "; start: () => Promise; } | undefined; fleet?: { setup: never; start: () => Promise<", - { - "pluginId": "fleet", - "scope": "server", - "docId": "kibFleetPluginApi", - "section": "def-server.FleetStartContract", - "text": "FleetStartContract" - }, - ">; } | undefined; home?: { setup: ", - { - "pluginId": "home", - "scope": "server", - "docId": "kibHomePluginApi", - "section": "def-server.HomeServerPluginSetup", - "text": "HomeServerPluginSetup" - }, - "; start: () => Promise<", - { - "pluginId": "home", - "scope": "server", - "docId": "kibHomePluginApi", - "section": "def-server.HomeServerPluginStart", - "text": "HomeServerPluginStart" - }, - ">; } | undefined; ml?: { setup: ", - { - "pluginId": "ml", - "scope": "server", - "docId": "kibMlPluginApi", - "section": "def-server.MlPluginSetup", - "text": "MlPluginSetup" - }, - "; start: () => Promise; } | undefined; security?: { setup: ", - { - "pluginId": "security", - "scope": "server", - "docId": "kibSecurityPluginApi", - "section": "def-server.SecurityPluginSetup", - "text": "SecurityPluginSetup" - }, - "; start: () => Promise<", - { - "pluginId": "security", - "scope": "server", - "docId": "kibSecurityPluginApi", - "section": "def-server.SecurityPluginStart", - "text": "SecurityPluginStart" - }, - ">; } | undefined; spaces?: { setup: ", - { - "pluginId": "spaces", - "scope": "server", - "docId": "kibSpacesPluginApi", - "section": "def-server.SpacesPluginSetup", - "text": "SpacesPluginSetup" - }, - "; start: () => Promise<", - { - "pluginId": "spaces", - "scope": "server", - "docId": "kibSpacesPluginApi", - "section": "def-server.SpacesPluginStart", - "text": "SpacesPluginStart" - }, - ">; } | undefined; taskManager?: { setup: ", - { - "pluginId": "taskManager", - "scope": "server", - "docId": "kibTaskManagerPluginApi", - "section": "def-server.TaskManagerSetupContract", - "text": "TaskManagerSetupContract" - }, - "; start: () => Promise<", - { - "pluginId": "taskManager", - "scope": "server", - "docId": "kibTaskManagerPluginApi", - "section": "def-server.TaskManagerStartContract", - "text": "TaskManagerStartContract" - }, - ">; } | undefined; usageCollection?: { setup: ", - { - "pluginId": "usageCollection", - "scope": "server", - "docId": "kibUsageCollectionPluginApi", - "section": "def-server.UsageCollectionSetup", - "text": "UsageCollectionSetup" - }, - "; start: () => Promise; } | undefined; customIntegrations?: { setup: ", - { - "pluginId": "customIntegrations", - "scope": "server", - "docId": "kibCustomIntegrationsPluginApi", - "section": "def-server.CustomIntegrationsPluginSetup", - "text": "CustomIntegrationsPluginSetup" - }, - "; start: () => Promise<", - { - "pluginId": "customIntegrations", - "scope": "server", - "docId": "kibCustomIntegrationsPluginApi", - "section": "def-server.CustomIntegrationsPluginStart", - "text": "CustomIntegrationsPluginStart" - }, - ">; } | undefined; }" - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.ruleDataClient", - "type": "Object", - "tags": [], - "label": "ruleDataClient", - "description": [], - "signature": [ - { - "pluginId": "ruleRegistry", - "scope": "server", - "docId": "kibRuleRegistryPluginApi", - "section": "def-server.IRuleDataClient", - "text": "IRuleDataClient" - } - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.telemetryUsageCounter", - "type": "Object", - "tags": [], - "label": "telemetryUsageCounter", - "description": [], - "signature": [ - { - "pluginId": "usageCollection", - "scope": "server", - "docId": "kibUsageCollectionPluginApi", - "section": "def-server.IUsageCounter", - "text": "IUsageCounter" - }, - " | undefined" - ], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMRouteHandlerResources.kibanaVersion", - "type": "string", - "tags": [], - "label": "kibanaVersion", - "description": [], - "path": "x-pack/plugins/apm/server/routes/typings.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - } - ], + "interfaces": [], "enums": [], "misc": [ { @@ -931,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, @@ -961,24 +438,9 @@ "label": "APMConfig", "description": [], "signature": [ - "{ readonly indices: Readonly<{} & { error: string; metric: string; transaction: string; span: string; onboarding: string; }>; readonly enabled: boolean; readonly autoCreateApmDataView: boolean; readonly serviceMapEnabled: boolean; readonly serviceMapFingerprintBucketSize: number; readonly serviceMapFingerprintGlobalBucketSize: number; readonly serviceMapTraceIdBucketSize: number; readonly serviceMapTraceIdGlobalBucketSize: number; readonly serviceMapMaxTracesPerRequest: number; readonly serviceMapTerminateAfter: number; readonly serviceMapMaxTraces: number; readonly ui: Readonly<{} & { enabled: boolean; maxTraceItems: number; }>; readonly searchAggregatedTransactions: ", + "{ readonly enabled: boolean; readonly autoCreateApmDataView: boolean; readonly serviceMapEnabled: boolean; readonly serviceMapFingerprintBucketSize: number; readonly serviceMapFingerprintGlobalBucketSize: number; readonly serviceMapTraceIdBucketSize: number; readonly serviceMapTraceIdGlobalBucketSize: number; readonly serviceMapMaxTracesPerRequest: number; readonly serviceMapTerminateAfter: number; readonly serviceMapMaxTraces: number; readonly ui: Readonly<{} & { enabled: boolean; maxTraceItems: number; }>; readonly searchAggregatedTransactions: ", "SearchAggregatedTransactionSetting", - "; readonly telemetryCollectionEnabled: boolean; readonly metricsInterval: number; readonly agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; readonly forceSyntheticSource: boolean; readonly latestAgentVersionsUrl: string; readonly serverlessOnboarding: boolean; readonly serverless: Readonly<{} & { enabled: true; }>; readonly managedServiceUrl: string; readonly featureFlags: Readonly<{} & { agentConfigurationAvailable: boolean; configurableIndicesAvailable: boolean; infrastructureTabAvailable: boolean; infraUiAvailable: boolean; migrationToFleetAvailable: boolean; sourcemapApiAvailable: boolean; storageExplorerAvailable: boolean; }>; }" - ], - "path": "x-pack/plugins/apm/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "apm", - "id": "def-server.ApmIndicesConfigName", - "type": "Type", - "tags": [], - "label": "ApmIndicesConfigName", - "description": [], - "signature": [ - "\"error\" | \"metric\" | \"transaction\" | \"span\" | \"onboarding\"" + "; readonly telemetryCollectionEnabled: boolean; readonly metricsInterval: number; readonly agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; readonly forceSyntheticSource: boolean; readonly latestAgentVersionsUrl: string; readonly serverless: Readonly<{} & { enabled: true; }>; readonly serverlessOnboarding: boolean; readonly managedServiceUrl: string; readonly featureFlags: Readonly<{} & { agentConfigurationAvailable: boolean; configurableIndicesAvailable: boolean; infrastructureTabAvailable: boolean; infraUiAvailable: boolean; migrationToFleetAvailable: boolean; sourcemapApiAvailable: boolean; storageExplorerAvailable: boolean; }>; }" ], "path": "x-pack/plugins/apm/server/index.ts", "deprecated": false, @@ -993,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", @@ -1009,14 +537,8 @@ "PartialC", "<{ 'service.environment': ", "StringC", - "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "; }>]>; }> | undefined; handler: ({}: ", + "APMRouteHandlerResources", " & { params: { query: { 'service.name': string; start: string; end: string; } & { 'service.environment'?: string | undefined; }; }; }) => Promise<{ content: ", "APMDownstreamDependency", "[]; }>; } & ", @@ -1112,13 +634,7 @@ "<", "CorrelationsEventType", ".Error>]>; }>>; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { sets: { foreground: { start: string; end: string; 'service.name': string; label: string; } & { filter?: string | undefined; 'service.environment'?: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { start: string; end: string; 'error.grouping_name': string; }; }; }) => Promise<{ content: Partial<", "APMError", "> | undefined; }>; } & ", @@ -1186,13 +696,7 @@ "; 'transaction.type': ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { 'service.name': string; start: string; end: string; } & { 'service.environment'?: string | undefined; 'transaction.type'?: string | undefined; }; }; }) => Promise<{ content: ", "ServiceSummary", "; }>; } & ", @@ -1314,13 +818,7 @@ "; end: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { stats: ({ 'service.environment': \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params?: { query?: { kuery?: string | undefined; start?: number | undefined; end?: number | undefined; } | undefined; } | undefined; }) => Promise<{ esResponses: { existingIndexTemplates: ", "IndicesGetIndexTemplateIndexTemplateItem", "[]; fieldCaps?: ", @@ -1381,7 +873,7 @@ "IngestGetPipelineResponse", " | undefined; }; diagnosticsPrivileges: { index: Record; cluster: Record; hasAllClusterPrivileges: boolean; hasAllIndexPrivileges: boolean; hasAllPrivileges: boolean; }; apmIndices: Readonly<{ error: string; onboarding: string; span: string; transaction: string; metric: 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", @@ -1440,13 +932,7 @@ "; fieldValues: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { offset?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; fieldName: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/get_latest_agent_versions\": { endpoint: \"GET /internal/apm/get_latest_agent_versions\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<", "AgentLatestVersionsResponse", ">; } & ", @@ -2116,13 +1542,7 @@ "; agentLanguage: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/settings/labs\": { endpoint: \"GET /internal/apm/settings/labs\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ labsItems: string[]; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/time_range_metadata\": { endpoint: \"GET /internal/apm/time_range_metadata\"; params?: ", @@ -2170,25 +1584,13 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { useSpanName: boolean; enableServiceTransactionMetrics: boolean; enableContinuousRollups: boolean; } & { kuery: string; } & { start: number; end: number; }; }; }) => Promise<", "TimeRangeMetadata", ">; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/debug-telemetry\": { endpoint: \"GET /internal/apm/debug-telemetry\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\": { endpoint: \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\"; params?: ", @@ -2230,13 +1632,7 @@ "text": "NonEmptyStringBrand" }, ">]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { traceId: string; spanId: string; }; query: { kuery: string; } & { start: number; end: number; }; }; }) => Promise<{ spanLinksDetails: ", "SpanLinkDetails", "[]; }>; } & ", @@ -2346,13 +1736,7 @@ "text": "ProcessorEvent" }, ".span>]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { traceId: string; spanId: string; }; query: { kuery: string; } & { start: number; end: number; } & { processorEvent: ", { "pluginId": "observability", @@ -2424,13 +1808,7 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { indexLifecyclePhase: ", "IndexLifecyclePhaseSelectOption", "; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -2446,13 +1824,7 @@ ">; } & { kuery: string; } & { start: number; end: number; }; }; }) => Promise<{ services: { serviceName: string; }[]; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/storage_explorer/is_cross_cluster_search\": { endpoint: \"GET /internal/apm/storage_explorer/is_cross_cluster_search\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ isCrossClusterSearch: boolean; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/storage_explorer_summary_stats\": { endpoint: \"GET /internal/apm/storage_explorer_summary_stats\"; params?: ", @@ -2518,13 +1890,7 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { indexLifecyclePhase: ", "IndexLifecyclePhaseSelectOption", "; } & { probability: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -2542,13 +1908,7 @@ ">; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/storage_explorer/privileges\": { endpoint: \"GET /internal/apm/storage_explorer/privileges\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ hasPrivileges: boolean; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/storage_chart\": { endpoint: \"GET /internal/apm/storage_chart\"; params?: ", @@ -2614,13 +1974,7 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { indexLifecyclePhase: ", "IndexLifecyclePhaseSelectOption", "; } & { probability: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -2704,13 +2058,7 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { indexLifecyclePhase: ", "IndexLifecyclePhaseSelectOption", "; } & { probability: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -2790,13 +2138,7 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { indexLifecyclePhase: ", "IndexLifecyclePhaseSelectOption", "; } & { probability: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -2832,13 +2174,7 @@ "<", "PrivilegeType", ".AGENT_CONFIG>]>>; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { name: string; privileges: ", "PrivilegeType", "[]; }; }; }) => Promise<", @@ -2852,37 +2188,19 @@ "<{ id: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { id: string; }; }; }) => Promise<", "InvalidateAgentKeyResponse", ">; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/agent_keys/privileges\": { endpoint: \"GET /internal/apm/agent_keys/privileges\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<", "AgentKeysPrivilegesResponse", ">; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/agent_keys\": { endpoint: \"GET /internal/apm/agent_keys\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<", "AgentKeysResponse", ">; } & ", @@ -2936,13 +2254,7 @@ ".span>]>; id: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { processorEvent: ", { "pluginId": "observability", @@ -2954,13 +2266,7 @@ "; id: string; }; }; }) => Promise<{ metadata: Partial>; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/has_data\": { endpoint: \"GET /internal/apm/has_data\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ hasData: boolean; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/fallback_to_transactions\": { endpoint: \"GET /internal/apm/fallback_to_transactions\"; params?: ", @@ -2978,13 +2284,7 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params?: { query?: ({ kuery: string; } & { start?: number | undefined; end?: number | undefined; }) | undefined; } | undefined; }) => Promise<{ fallbackToTransactions: boolean; }>; } & ", "APMRouteCreateOptions", "; \"POST /internal/apm/correlations/p_values/transactions\": { endpoint: \"POST /internal/apm/correlations/p_values/transactions\"; params?: ", @@ -3040,13 +2340,7 @@ "<", "StringC", ">; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { serviceName?: string | undefined; transactionName?: string | undefined; transactionType?: string | undefined; durationMin?: number | undefined; durationMax?: number | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }>>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { serviceName?: string | undefined; transactionName?: string | undefined; transactionType?: string | undefined; durationMin?: number | undefined; durationMax?: number | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { serviceName?: string | undefined; transactionName?: string | undefined; transactionType?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { serviceName?: string | undefined; transactionName?: string | undefined; transactionType?: string | undefined; samplerShardSize?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { serviceName?: string | undefined; transactionName?: string | undefined; transactionType?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; sampleRangeTo: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { dependencyName: string; spanName: string; percentileThreshold: number; } & { start: number; end: number; } & { kuery: string; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { dependencyName: string; spanName: string; searchServiceDestinationMetrics: boolean; } & { start: number; end: number; } & { kuery: string; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { dependencyName: string; spanName: string; searchServiceDestinationMetrics: boolean; } & { start: number; end: number; } & { kuery: string; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { dependencyName: string; spanName: string; searchServiceDestinationMetrics: boolean; } & { start: number; end: number; } & { kuery: string; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { dependencyName: string; } & { start: number; end: number; }; }; }) => Promise<{ metadata: ", "MetadataForDependencyResponse", "; }>; } & ", @@ -3832,13 +3060,7 @@ "<{ kuery: ", "StringC", "; }>]>; }>]> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { dependencyName: string; } & { start: number; end: number; } & { numBuckets: number; }; } & { query?: ({ environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; }>]> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/fleet/java_agent_versions\": { endpoint: \"GET /internal/apm/fleet/java_agent_versions\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ versions: string[] | undefined; }>; } & ", "APMRouteCreateOptions", "; \"POST /internal/apm/fleet/cloud_apm_package_policy\": { endpoint: \"POST /internal/apm/fleet/cloud_apm_package_policy\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ cloudApmPackagePolicy: ", { "pluginId": "fleet", @@ -3950,25 +3154,13 @@ "; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/fleet/migration_check\": { endpoint: \"GET /internal/apm/fleet/migration_check\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<", "RunMigrationCheckResponse", ">; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/fleet/apm_server_schema/unsupported\": { endpoint: \"GET /internal/apm/fleet/apm_server_schema/unsupported\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ unsupported: ", "UnsupportedApmServerSchema", "; }>; } & ", @@ -3984,45 +3176,21 @@ ", ", "UnknownC", ">; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { schema: { [x: string]: unknown; }; }; }; }) => Promise; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/fleet/agents\": { endpoint: \"GET /internal/apm/fleet/agents\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<", "FleetAgentResponse", ">; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/fleet/has_apm_policies\": { endpoint: \"GET /internal/apm/fleet/has_apm_policies\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ hasApmPolicies: boolean; }>; } & ", "APMRouteCreateOptions", "; \"POST /internal/apm/sourcemaps/migrate_fleet_artifacts\": { endpoint: \"POST /internal/apm/sourcemaps/migrate_fleet_artifacts\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise; } & ", "APMRouteCreateOptions", "; \"POST /api/apm/androidmaps 2023-10-31\": { endpoint: \"POST /api/apm/androidmaps 2023-10-31\"; params?: ", @@ -4036,13 +3204,7 @@ "; map_file: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { service_name: string; service_version: string; map_file: string; }; }; }) => Promise<", { "pluginId": "fleet", @@ -4060,13 +3222,7 @@ "<{ id: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { id: string; }; }; }) => Promise; } & ", "APMRouteCreateOptions", "; \"POST /api/apm/sourcemaps 2023-10-31\": { endpoint: \"POST /api/apm/sourcemaps 2023-10-31\"; params?: ", @@ -4082,13 +3238,7 @@ "; sourcemap: ", "Type", "<{ version: number; sources: string[]; mappings: string; } & { names?: string[] | undefined; file?: string | undefined; sourceRoot?: string | undefined; sourcesContent?: (string | null)[] | undefined; }, string | Buffer, unknown>; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { service_name: string; service_version: string; bundle_filepath: string; sourcemap: { version: number; sources: string[]; mappings: string; } & { names?: string[] | undefined; file?: string | undefined; sourceRoot?: string | undefined; sourcesContent?: (string | null)[] | undefined; }; }; }; }) => Promise<", { "pluginId": "fleet", @@ -4108,13 +3258,7 @@ "; perPage: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params?: { query?: { page?: number | undefined; perPage?: number | undefined; } | undefined; } | undefined; }) => Promise<", "ListSourceMapArtifactsResponse", " | undefined>; } & ", @@ -4126,13 +3270,7 @@ "<{ id: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { id: string; }; }; }) => Promise<{ result: string; }>; } & ", "APMRouteCreateOptions", "; \"PUT /internal/apm/settings/custom_links/{id}\": { endpoint: \"PUT /internal/apm/settings/custom_links/{id}\"; params?: ", @@ -4174,13 +3312,7 @@ "; }>]>; value: ", "StringC", "; }>>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { id: string; }; body: { label: string; url: string; } & { id?: string | undefined; filters?: { key: \"\" | \"service.name\" | \"service.environment\" | \"transaction.name\" | \"transaction.type\"; value: string; }[] | undefined; }; }; }) => Promise; } & ", "APMRouteCreateOptions", "; \"POST /internal/apm/settings/custom_links\": { endpoint: \"POST /internal/apm/settings/custom_links\"; params?: ", @@ -4218,13 +3350,7 @@ "; }>]>; value: ", "StringC", "; }>>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { label: string; url: string; } & { id?: string | undefined; filters?: { key: \"\" | \"service.name\" | \"service.environment\" | \"transaction.name\" | \"transaction.type\"; value: string; }[] | undefined; }; }; }) => Promise; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/settings/custom_links\": { endpoint: \"GET /internal/apm/settings/custom_links\"; params?: ", @@ -4240,13 +3366,7 @@ "; 'transaction.type': ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params?: { query?: { 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; } | undefined; } | undefined; }) => Promise<{ customLinks: ", "CustomLink", "[]; }>; } & ", @@ -4264,13 +3384,7 @@ "; 'transaction.type': ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params?: { query?: { 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; } | undefined; } | undefined; }) => Promise<", "Transaction", ">; } & ", @@ -4280,14 +3394,8 @@ "<{ body: ", "PartialC", "; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, - " & { params: { body: { readonly error?: string | undefined; readonly metric?: string | undefined; readonly transaction?: string | undefined; readonly span?: string | undefined; readonly onboarding?: string | undefined; }; }; }) => Promise<", + "APMRouteHandlerResources", + " & { 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", @@ -4298,45 +3406,21 @@ "<{}>>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/settings/apm-indices\": { endpoint: \"GET /internal/apm/settings/apm-indices\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, - ") => Promise>; } & ", + "APMRouteHandlerResources", + ") => Promise>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/settings/apm-index-settings\": { endpoint: \"GET /internal/apm/settings/apm-index-settings\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ apmIndexSettings: ", "ApmIndexSettingsResponse", "; }>; } & ", "APMRouteCreateOptions", "; \"POST /internal/apm/settings/anomaly-detection/update_to_v3\": { endpoint: \"POST /internal/apm/settings/anomaly-detection/update_to_v3\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ update: boolean; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/settings/anomaly-detection/environments\": { endpoint: \"GET /internal/apm/settings/anomaly-detection/environments\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ environments: string[]; }>; } & ", "APMRouteCreateOptions", "; \"POST /internal/apm/settings/anomaly-detection/jobs\": { endpoint: \"POST /internal/apm/settings/anomaly-detection/jobs\"; params?: ", @@ -4364,13 +3448,7 @@ "text": "NonEmptyStringBrand" }, ">]>>; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { environments: (\"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", ")[]; }; }; }) => Promise<{ jobCreated: true; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/settings/anomaly-detection/jobs\": { endpoint: \"GET /internal/apm/settings/anomaly-detection/jobs\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ jobs: ", "ApmMlJob", "[]; hasLegacyJobs: boolean; }>; } & ", @@ -4402,13 +3474,7 @@ "<{ serviceName: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { serviceName: string; }; }; }) => Promise<{ agentName: string | undefined; }>; } & ", "APMRouteCreateOptions", "; \"GET /api/apm/settings/agent-configuration/environments 2023-10-31\": { endpoint: \"GET /api/apm/settings/agent-configuration/environments 2023-10-31\"; params?: ", @@ -4418,13 +3484,7 @@ "<{ serviceName: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params?: { query?: { serviceName?: string | undefined; } | undefined; } | undefined; }) => Promise<{ environments: ", "EnvironmentsResponse", "; }>; } & ", @@ -4448,13 +3508,7 @@ "; mark_as_applied_by_agent: ", "BooleanC", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { service: { name?: string | undefined; environment?: string | undefined; }; } & { etag?: string | undefined; mark_as_applied_by_agent?: boolean | undefined; }; }; }) => Promise<", { "pluginId": "@kbn/es-types", @@ -4504,13 +3558,7 @@ ">]>; }>]>; }>]> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query?: { overwrite?: boolean | undefined; } | undefined; } & { body: { agent_name?: string | undefined; } & { service: { name?: string | undefined; environment?: string | undefined; }; settings: { [x: string]: string; } & { [x: string]: any; }; }; }; }) => Promise; } & ", "APMRouteCreateOptions", "; \"DELETE /api/apm/settings/agent-configuration 2023-10-31\": { endpoint: \"DELETE /api/apm/settings/agent-configuration 2023-10-31\"; params?: ", @@ -4524,13 +3572,7 @@ "; environment: ", "StringC", "; }>; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { service: { name?: string | undefined; environment?: string | undefined; }; }; }; }) => Promise<{ result: string; }>; } & ", "APMRouteCreateOptions", "; \"GET /api/apm/settings/agent-configuration/view 2023-10-31\": { endpoint: \"GET /api/apm/settings/agent-configuration/view 2023-10-31\"; params?: ", @@ -4542,25 +3584,13 @@ "; environment: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params?: { query?: { name?: string | undefined; environment?: string | undefined; } | undefined; } | undefined; }) => Promise<", "AgentConfiguration", ">; } & ", "APMRouteCreateOptions", "; \"GET /api/apm/settings/agent-configuration 2023-10-31\": { endpoint: \"GET /api/apm/settings/agent-configuration 2023-10-31\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ configurations: ", "AgentConfiguration", "[]; }>; } & ", @@ -4629,16 +3659,10 @@ "ArrayC", "<", "StringC", - ">; kqlFilter: ", - "StringC", - "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + ">; searchConfiguration: ", + "Type", + "<{ query: { query: string | { [x: string]: any; }; language: string; }; }, string, unknown>; }>]>; }> | undefined; handler: ({}: ", + "APMRouteHandlerResources", " & { params: { query: { aggregationType?: ", "AggregationType", " | undefined; serviceName?: string | undefined; errorGroupingKey?: string | undefined; transactionType?: string | undefined; transactionName?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -4651,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", @@ -4719,16 +3743,10 @@ "ArrayC", "<", "StringC", - ">; kqlFilter: ", - "StringC", - "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + ">; searchConfiguration: ", + "Type", + "<{ query: { query: string | { [x: string]: any; }; language: string; }; }, string, unknown>; }>]>; }> | undefined; handler: ({}: ", + "APMRouteHandlerResources", " & { params: { query: { aggregationType?: ", "AggregationType", " | undefined; serviceName?: string | undefined; errorGroupingKey?: string | undefined; transactionType?: string | undefined; transactionName?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -4741,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", @@ -4809,16 +3827,10 @@ "ArrayC", "<", "StringC", - ">; kqlFilter: ", - "StringC", - "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + ">; searchConfiguration: ", + "Type", + "<{ query: { query: string | { [x: string]: any; }; language: string; }; }, string, unknown>; }>]>; }> | undefined; handler: ({}: ", + "APMRouteHandlerResources", " & { params: { query: { aggregationType?: ", "AggregationType", " | undefined; serviceName?: string | undefined; errorGroupingKey?: string | undefined; transactionType?: string | undefined; transactionName?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -4831,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", @@ -4886,13 +3898,7 @@ "<{ offset: ", "StringC", "; }>]>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { transactionType: string; transactionName: string; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { transactionType: string; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }>]>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { transactionType: string; bucketSizeInSeconds: number; } & { transactionName?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { transactionType: string; } & { transactionName?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { transactionType: string; transactionName: string; } & { transactionId?: string | undefined; traceId?: string | undefined; sampleRangeFrom?: number | undefined; sampleRangeTo?: number | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { transactionType: string; latencyAggregationType: ", "LatencyAggregationType", "; bucketSizeInSeconds: number; useDurationSummary: boolean; } & { transactionName?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -5476,13 +4452,7 @@ "<", "LatencyAggregationType", ".p99>]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", ", ", "UndefinedC", "]>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { traceId: string; spanId: string; }; query: { start: number; end: number; } & { parentTransactionId?: string | undefined; }; }; }) => Promise<{ span?: ", "Span", " | undefined; parentTransaction?: ", @@ -5676,13 +4634,7 @@ "; end: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { traceId: string; transactionId: string; }; query: { start: number; end: number; }; }; }) => Promise<", "Transaction", ">; } & ", @@ -5736,13 +4688,7 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { traceIds: string[]; serviceName: ", "Branded", "]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { transactionId: string; }; query: { start: number; end: number; }; }; }) => Promise<{ transaction: ", "Transaction", "; }>; } & ", @@ -5872,13 +4806,7 @@ "; end: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { traceId: string; }; query: { start: number; end: number; }; }; }) => Promise<{ transaction: ", "Transaction", "; }>; } & ", @@ -5920,15 +4848,9 @@ "; }>, ", "TypeC", "<{ probability: ", - "Type", - "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "Type", + "; }>]>; }> | undefined; handler: ({}: ", + "APMRouteHandlerResources", " & { params: { query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { traceId: string; }; query: { start: number; end: number; } & { entryTransactionId: string; }; }; }) => Promise<{ traceItems: ", "TraceItems", "; entryTransaction?: ", @@ -5996,23 +4912,11 @@ "<{ serviceName: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { fieldName: string; fieldValue: string; } & { start: number; end: number; } & { serviceName?: string | undefined; }; }; }) => Promise<{ terms: string[]; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/service-group/counts\": { endpoint: \"GET /internal/apm/service-group/counts\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/service-group/services\": { endpoint: \"GET /internal/apm/service-group/services\"; params?: ", @@ -6030,13 +4934,7 @@ "<{ kuery: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { start: number; end: number; } & { kuery?: string | undefined; }; }; }) => Promise<{ items: ", "LookupServicesResponse", "; }>; } & ", @@ -6048,13 +4946,7 @@ "<{ serviceGroupId: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { serviceGroupId: string; }; }; }) => Promise; } & ", "APMRouteCreateOptions", "; \"POST /internal/apm/service-group\": { endpoint: \"POST /internal/apm/service-group\"; params?: ", @@ -6086,13 +4978,7 @@ ", ", "UndefinedC", "]>; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { serviceGroupId?: string | undefined; } | undefined; body: { groupName: string; kuery: string; description: string | undefined; color: string | undefined; }; }; }) => Promise<", "SavedServiceGroup", ">; } & ", @@ -6104,25 +4990,13 @@ "<{ serviceGroup: ", "StringC", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { serviceGroup: string; }; }; }) => Promise<{ serviceGroup: ", "SavedServiceGroup", "; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/service-groups\": { endpoint: \"GET /internal/apm/service-groups\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ serviceGroups: ", "SavedServiceGroup", "[]; }>; } & ", @@ -6162,13 +5036,7 @@ "text": "NonEmptyStringBrand" }, ">]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { numBuckets: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { latencyAggregationType: ", "LatencyAggregationType", "; transactionType: string; serviceNodeIds: string[]; numBuckets: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -6514,13 +5358,7 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { latencyAggregationType: ", "LatencyAggregationType", "; transactionType: string; } & { offset?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", @@ -6628,13 +5466,7 @@ "<", "RollupInterval", ".None>]>; }>]>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { transactionType: string; bucketSizeInSeconds: number; } & { transactionName?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; serviceNodeName: string; }; query: { start: number; end: number; }; }; }) => Promise<", "ServiceInstanceMetadataDetailsResponse", " & ({} | ", @@ -6718,13 +5544,7 @@ "<", "StringC", ">; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; body: { '@timestamp': number; service: { version: string; } & { environment?: string | undefined; }; } & { message?: string | undefined; tags?: string[] | undefined; }; }; }) => Promise<{ _id: string; _index: string; _source: ", "Annotation", "; }>; } & ", @@ -6764,13 +5584,7 @@ "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; serviceNodeName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { start: number; end: number; }; }; }) => Promise<", "ServiceTransactionTypesResponse", ">; } & ", @@ -6884,13 +5686,7 @@ "; end: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { start: number; end: number; }; }; }) => Promise<", "ServiceAgentResponse", ">; } & ", @@ -6908,13 +5704,7 @@ "; end: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { start: number; end: number; }; }; }) => Promise<", "ServiceMetadataIcons", ">; } & ", @@ -6932,13 +5722,7 @@ "; end: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { start: number; end: number; }; }; }) => Promise<", "ServiceMetadataDetails", ">; } & ", @@ -7030,13 +5814,7 @@ "<{ serviceNames: ", "Type", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { serviceGroup?: string | undefined; } & { probability: number; } & { documentType: ", "ApmDocumentType", ".TransactionMetric | ", @@ -7206,13 +5978,7 @@ "<{ offset: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { dependencyName: string; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { serviceName?: string | undefined; serviceGroup?: string | undefined; kuery?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/observability_overview/has_data\": { endpoint: \"GET /internal/apm/observability_overview/has_data\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<", "HasDataResponse", ">; } & ", @@ -7376,13 +6124,7 @@ "; intervalString: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { start: number; end: number; } & { bucketSize: number; intervalString: string; }; }; }) => Promise<", "ObservabilityOverviewResponse", ">; } & ", @@ -7430,13 +6172,7 @@ "<{ serverlessId: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; }>]>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { kuery: string; } & { start: number; end: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { agentName: string; } & { serviceNodeName?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { body: { serviceName?: string | undefined; transactionName?: string | undefined; transactionType?: string | undefined; termFilters?: { fieldName: string; fieldValue: string | number; }[] | undefined; durationMin?: number | undefined; durationMax?: number | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; groupId: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { groupId?: string | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; groupId: string; errorId: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; groupId: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; }>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { transactionType: string; transactionName: string; maxNumberOfErrorGroups: number; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { path: { serviceName: string; }; query: { sortField?: string | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; } & { environment: \"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", "; end: ", "Type", "; }>]>; }> | undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", " & { params: { query: { serviceName?: string | undefined; } & { start: number; end: number; }; }; }) => Promise<{ environments: (\"ENVIRONMENT_NOT_DEFINED\" | \"ENVIRONMENT_ALL\" | ", "Branded", ")[]; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/data_view/title\": { endpoint: \"GET /internal/apm/data_view/title\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ apmDataViewTitle: string; }>; } & ", "APMRouteCreateOptions", "; \"POST /internal/apm/data_view/static\": { endpoint: \"POST /internal/apm/data_view/static\"; params?: undefined; handler: ({}: ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, + "APMRouteHandlerResources", ") => Promise<{ created: boolean; dataView: ", { "pluginId": "dataViews", @@ -8480,151 +7120,13 @@ "description": [], "signature": [ "Observable", - "; enabled: boolean; autoCreateApmDataView: boolean; serviceMapEnabled: boolean; serviceMapFingerprintBucketSize: number; serviceMapFingerprintGlobalBucketSize: number; serviceMapTraceIdBucketSize: number; serviceMapTraceIdGlobalBucketSize: number; serviceMapMaxTracesPerRequest: number; serviceMapTerminateAfter: number; serviceMapMaxTraces: number; ui: Readonly<{} & { enabled: boolean; maxTraceItems: number; }>; searchAggregatedTransactions: ", + "; searchAggregatedTransactions: ", "SearchAggregatedTransactionSetting", - "; telemetryCollectionEnabled: boolean; metricsInterval: number; agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; forceSyntheticSource: boolean; latestAgentVersionsUrl: string; serverlessOnboarding: boolean; serverless: Readonly<{} & { enabled: true; }>; managedServiceUrl: string; featureFlags: Readonly<{} & { agentConfigurationAvailable: boolean; configurableIndicesAvailable: boolean; infrastructureTabAvailable: boolean; infraUiAvailable: boolean; migrationToFleetAvailable: boolean; sourcemapApiAvailable: boolean; storageExplorerAvailable: boolean; }>; }>>" + "; telemetryCollectionEnabled: boolean; metricsInterval: number; agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; forceSyntheticSource: boolean; latestAgentVersionsUrl: string; serverless: Readonly<{} & { enabled: true; }>; serverlessOnboarding: boolean; managedServiceUrl: string; featureFlags: Readonly<{} & { agentConfigurationAvailable: boolean; configurableIndicesAvailable: boolean; infrastructureTabAvailable: boolean; infraUiAvailable: boolean; migrationToFleetAvailable: boolean; sourcemapApiAvailable: boolean; storageExplorerAvailable: boolean; }>; }>>" ], "path": "x-pack/plugins/apm/server/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMPluginSetup.getApmIndices", - "type": "Function", - "tags": [], - "label": "getApmIndices", - "description": [], - "signature": [ - "() => Promise>" - ], - "path": "x-pack/plugins/apm/server/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "apm", - "id": "def-server.APMPluginSetup.createApmEventClient", - "type": "Function", - "tags": [], - "label": "createApmEventClient", - "description": [], - "signature": [ - "(params: { debug?: boolean | undefined; request: ", - { - "pluginId": "@kbn/core-http-server", - "scope": "common", - "docId": "kibKbnCoreHttpServerPluginApi", - "section": "def-common.KibanaRequest", - "text": "KibanaRequest" - }, - "; context: ", - "ApmPluginRequestHandlerContext", - "; }) => Promise<", - "APMEventClient", - ">" - ], - "path": "x-pack/plugins/apm/server/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "apm", - "id": "def-server.APMPluginSetup.createApmEventClient.$1", - "type": "Object", - "tags": [], - "label": "params", - "description": [], - "path": "x-pack/plugins/apm/server/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "apm", - "id": "def-server.APMPluginSetup.createApmEventClient.$1.debug", - "type": "CompoundType", - "tags": [], - "label": "debug", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "x-pack/plugins/apm/server/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMPluginSetup.createApmEventClient.$1.request", - "type": "Object", - "tags": [], - "label": "request", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-server", - "scope": "common", - "docId": "kibKbnCoreHttpServerPluginApi", - "section": "def-common.KibanaRequest", - "text": "KibanaRequest" - }, - "" - ], - "path": "x-pack/plugins/apm/server/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "apm", - "id": "def-server.APMPluginSetup.createApmEventClient.$1.context", - "type": "CompoundType", - "tags": [], - "label": "context", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-request-handler-context-server", - "scope": "common", - "docId": "kibKbnCoreHttpRequestHandlerContextServerPluginApi", - "section": "def-common.RequestHandlerContext", - "text": "RequestHandlerContext" - }, - " & { licensing: Promise<", - { - "pluginId": "licensing", - "scope": "server", - "docId": "kibLicensingPluginApi", - "section": "def-server.LicensingApiRequestHandlerContext", - "text": "LicensingApiRequestHandlerContext" - }, - ">; alerting: Promise<", - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.AlertingApiRequestHandlerContext", - "text": "AlertingApiRequestHandlerContext" - }, - ">; rac: Promise<", - { - "pluginId": "ruleRegistry", - "scope": "server", - "docId": "kibRuleRegistryPluginApi", - "section": "def-server.RacApiRequestHandlerContext", - "text": "RacApiRequestHandlerContext" - }, - ">; }" - ], - "path": "x-pack/plugins/apm/server/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [] } ], "lifecycle": "setup", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 371ecef52af79..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 48 | 0 | 48 | 120 | +| 29 | 0 | 29 | 119 | ## Client @@ -42,9 +42,6 @@ Contact [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) for ques ### Classes -### Interfaces - - ### Consts, variables and types diff --git a/api_docs/apm_data_access.devdocs.json b/api_docs/apm_data_access.devdocs.json new file mode 100644 index 0000000000000..57fe58d681f92 --- /dev/null +++ b/api_docs/apm_data_access.devdocs.json @@ -0,0 +1,178 @@ +{ + "id": "apmDataAccess", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "apmDataAccess", + "id": "def-server.APMDataAccessConfig", + "type": "Type", + "tags": [], + "label": "APMDataAccessConfig", + "description": [], + "signature": [ + "{ 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, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "apmDataAccess", + "id": "def-server.APMIndices", + "type": "Type", + "tags": [], + "label": "APMIndices", + "description": [], + "signature": [ + "{ 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, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [], + "setup": { + "parentPluginId": "apmDataAccess", + "id": "def-server.ApmDataAccessPluginSetup", + "type": "Interface", + "tags": [], + "label": "ApmDataAccessPluginSetup", + "description": [], + "path": "x-pack/plugins/apm_data_access/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "apmDataAccess", + "id": "def-server.ApmDataAccessPluginSetup.apmIndicesFromConfigFile", + "type": "Object", + "tags": [], + "label": "apmIndicesFromConfigFile", + "description": [], + "signature": [ + "{ 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, + "trackAdoption": false + }, + { + "parentPluginId": "apmDataAccess", + "id": "def-server.ApmDataAccessPluginSetup.getApmIndices", + "type": "Function", + "tags": [], + "label": "getApmIndices", + "description": [], + "signature": [ + "(soClient: ", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-common.SavedObjectsClientContract", + "text": "SavedObjectsClientContract" + }, + ") => Promise>" + ], + "path": "x-pack/plugins/apm_data_access/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "apmDataAccess", + "id": "def-server.ApmDataAccessPluginSetup.getApmIndices.$1", + "type": "Object", + "tags": [], + "label": "soClient", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-common.SavedObjectsClientContract", + "text": "SavedObjectsClientContract" + } + ], + "path": "x-pack/plugins/apm_data_access/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "lifecycle": "setup", + "initialIsOpen": true + }, + "start": { + "parentPluginId": "apmDataAccess", + "id": "def-server.ApmDataAccessPluginStart", + "type": "Interface", + "tags": [], + "label": "ApmDataAccessPluginStart", + "description": [], + "path": "x-pack/plugins/apm_data_access/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "lifecycle": "start", + "initialIsOpen": true + } + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "apmDataAccess", + "id": "def-common.PLUGIN_ID", + "type": "string", + "tags": [], + "label": "PLUGIN_ID", + "description": [], + "signature": [ + "\"apmDataAccess\"" + ], + "path": "x-pack/plugins/apm_data_access/common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "apmDataAccess", + "id": "def-common.PLUGIN_NAME", + "type": "string", + "tags": [], + "label": "PLUGIN_NAME", + "description": [], + "signature": [ + "\"apmDataAccess\"" + ], + "path": "x-pack/plugins/apm_data_access/common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx new file mode 100644 index 0000000000000..13727c4c1f12b --- /dev/null +++ b/api_docs/apm_data_access.mdx @@ -0,0 +1,41 @@ +--- +#### +#### 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: kibApmDataAccessPluginApi +slug: /kibana-dev-docs/api/apmDataAccess +title: "apmDataAccess" +image: https://source.unsplash.com/400x175/?github +description: API docs for the apmDataAccess plugin +date: 2023-09-04 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] +--- +import apmDataAccessObj from './apm_data_access.devdocs.json'; + + + +Contact [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 9 | 0 | 9 | 0 | + +## Server + +### Setup + + +### Start + + +### Consts, variables and types + + +## Common + +### Consts, variables and types + + diff --git a/api_docs/asset_manager.mdx b/api_docs/asset_manager.mdx index 4e8d0114d9e55..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-22 +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 bb200ec48dec3..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-22 +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 ebefb81f8cbc7..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-22 +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 13131319104aa..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-22 +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 b749532e5f360..5d00886d09ee8 100644 --- a/api_docs/cases.devdocs.json +++ b/api_docs/cases.devdocs.json @@ -70,7 +70,7 @@ "section": "def-public.ICasesDeepLinkId", "text": "ICasesDeepLinkId" }, - ", Partial>> | undefined; }) => { id: \"cases\"; path: string; deepLinks: ({ id: \"cases_create\"; path: string; title: any; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; category?: T[\"category\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; deepLinks?: T[\"deepLinks\"] | undefined; } | { id: \"cases_configure\"; path: string; title: any; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; category?: T[\"category\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; deepLinks?: T[\"deepLinks\"] | undefined; })[]; title: any; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; category?: T[\"category\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; }" + ", Partial>> | undefined; }) => { id: \"cases\"; path: string; deepLinks: ({ id: \"cases_create\"; path: string; title: string | T[\"title\"]; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; category?: T[\"category\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; deepLinks?: T[\"deepLinks\"] | undefined; } | { id: \"cases_configure\"; path: string; title: string | T[\"title\"]; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; category?: T[\"category\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; deepLinks?: T[\"deepLinks\"] | undefined; })[]; title: string | T[\"title\"]; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; category?: T[\"category\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; }" ], "path": "x-pack/plugins/cases/public/common/navigation/deep_links.ts", "deprecated": false, @@ -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 64f299ea9b310..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-22 +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.devdocs.json b/api_docs/charts.devdocs.json index b8c332abcc153..e3d53d5208a1d 100644 --- a/api_docs/charts.devdocs.json +++ b/api_docs/charts.devdocs.json @@ -1576,13 +1576,10 @@ { "parentPluginId": "charts", "id": "def-public.defaultCountLabel", - "type": "Any", + "type": "string", "tags": [], "label": "defaultCountLabel", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/components/collections.ts", "deprecated": false, "trackAdoption": false, @@ -1660,7 +1657,7 @@ "label": "LabelRotation", "description": [], "signature": [ - "{ readonly Horizontal: number; readonly Vertical: number; readonly Angled: number; }" + "{ readonly Horizontal: number; readonly Vertical: number; readonly Angled: number; readonly VerticalRotation: number; }" ], "path": "src/plugins/charts/common/static/components/collections.ts", "deprecated": false, @@ -1868,13 +1865,10 @@ { "parentPluginId": "charts", "id": "def-public.vislibColorMaps.ColorSchemas.Blues.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -1930,13 +1924,10 @@ { "parentPluginId": "charts", "id": "def-public.vislibColorMaps.ColorSchemas.Greens.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -1992,13 +1983,10 @@ { "parentPluginId": "charts", "id": "def-public.vislibColorMaps.ColorSchemas.Greys.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -2054,13 +2042,10 @@ { "parentPluginId": "charts", "id": "def-public.vislibColorMaps.ColorSchemas.Reds.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -2116,13 +2101,10 @@ { "parentPluginId": "charts", "id": "def-public.vislibColorMaps.ColorSchemas.YellowToRed.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -2178,13 +2160,10 @@ { "parentPluginId": "charts", "id": "def-public.vislibColorMaps.ColorSchemas.GreenToRed.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -3374,7 +3353,7 @@ "label": "AllowedSettingsOverrides", "description": [], "signature": [ - "{ settings?: { debug?: boolean | undefined; theme?: ", + "{ settings?: { theme?: ", "MakeOverridesSerializable", "<", "RecursivePartial", @@ -3390,7 +3369,7 @@ "LegendPositionConfig", " | undefined; rotation?: ", "Rotation", - " | undefined; ariaLabelHeadingLevel?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | undefined; ariaUseDefaultSummary?: boolean | undefined; flatLegend?: boolean | undefined; legendMaxDepth?: number | undefined; legendSize?: number | undefined; showLegendExtra?: boolean | undefined; rendering?: ", + " | undefined; debug?: boolean | undefined; ariaLabelHeadingLevel?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | undefined; ariaUseDefaultSummary?: boolean | undefined; flatLegend?: boolean | undefined; legendMaxDepth?: number | undefined; legendSize?: number | undefined; showLegendExtra?: boolean | undefined; rendering?: ", "Rendering", " | undefined; animateData?: boolean | undefined; externalPointerEvents?: ", "MakeOverridesSerializable", @@ -3470,13 +3449,10 @@ { "parentPluginId": "charts", "id": "def-common.defaultCountLabel", - "type": "Any", + "type": "string", "tags": [], "label": "defaultCountLabel", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/components/collections.ts", "deprecated": false, "trackAdoption": false, @@ -3623,7 +3599,7 @@ "label": "LabelRotation", "description": [], "signature": [ - "{ readonly Horizontal: number; readonly Vertical: number; readonly Angled: number; }" + "{ readonly Horizontal: number; readonly Vertical: number; readonly Angled: number; readonly VerticalRotation: number; }" ], "path": "src/plugins/charts/common/static/components/collections.ts", "deprecated": false, @@ -3831,13 +3807,10 @@ { "parentPluginId": "charts", "id": "def-common.vislibColorMaps.ColorSchemas.Blues.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -3893,13 +3866,10 @@ { "parentPluginId": "charts", "id": "def-common.vislibColorMaps.ColorSchemas.Greens.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -3955,13 +3925,10 @@ { "parentPluginId": "charts", "id": "def-common.vislibColorMaps.ColorSchemas.Greys.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -4017,13 +3984,10 @@ { "parentPluginId": "charts", "id": "def-common.vislibColorMaps.ColorSchemas.Reds.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -4079,13 +4043,10 @@ { "parentPluginId": "charts", "id": "def-common.vislibColorMaps.ColorSchemas.YellowToRed.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false @@ -4141,13 +4102,10 @@ { "parentPluginId": "charts", "id": "def-common.vislibColorMaps.ColorSchemas.GreenToRed.label", - "type": "Any", + "type": "string", "tags": [], "label": "label", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/charts/common/static/color_maps/color_maps.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 48b127dfd0d7d..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.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 | |-------------------|-----------|------------------------|-----------------| -| 268 | 16 | 253 | 10 | +| 268 | 2 | 253 | 10 | ## Client diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 40d3ccad9780e..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-22 +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 b6dd61ebdcc36..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-22 +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 66f429f968b29..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-22 +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.devdocs.json b/api_docs/cloud_data_migration.devdocs.json index 46a118a592a92..752512ce7b863 100644 --- a/api_docs/cloud_data_migration.devdocs.json +++ b/api_docs/cloud_data_migration.devdocs.json @@ -144,13 +144,10 @@ { "parentPluginId": "cloudDataMigration", "id": "def-common.PLUGIN_NAME", - "type": "Any", + "type": "string", "tags": [], "label": "PLUGIN_NAME", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/cloud_integrations/cloud_data_migration/common/index.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index 407165f9528d5..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/platform-onboarding](https://github.com/orgs/elastic/teams/pla | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 8 | 1 | 8 | 1 | +| 8 | 0 | 8 | 1 | ## Client diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index ec3778b98074d..8164d8ba931d5 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,14 +8,14 @@ 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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; Defend for containers (D4C) -Contact [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/teams/sec-cloudnative-integrations) for questions regarding this plugin. +Contact [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index b644ba0d74fac..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-22 +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 2446fa1d0e038..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-22 +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 8881efeab2d3d..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-22 +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 5e8fc2d2e776d..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.devdocs.json b/api_docs/controls.devdocs.json index e8be4c1768a68..5f249c50c376d 100644 --- a/api_docs/controls.devdocs.json +++ b/api_docs/controls.devdocs.json @@ -1551,7 +1551,7 @@ "label": "getDisplayName", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "src/plugins/controls/public/control_group/embeddable/control_group_container_factory.ts", "deprecated": false, @@ -2669,7 +2669,7 @@ "label": "getDisplayName", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable_factory.tsx", "deprecated": false, @@ -2701,7 +2701,7 @@ "label": "getDescription", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable_factory.tsx", "deprecated": false, @@ -3381,7 +3381,7 @@ "label": "getDisplayName", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable_factory.tsx", "deprecated": false, @@ -3397,7 +3397,7 @@ "label": "getDescription", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable_factory.tsx", "deprecated": false, @@ -6862,7 +6862,7 @@ "label": "newState", "description": [], "signature": [ - "{ viewMode?: ", + "{ version?: string | undefined; viewMode?: ", { "pluginId": "embeddable", "scope": "common", diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 1674d723cbc35..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-22 +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 b1be4828778fc..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.devdocs.json b/api_docs/dashboard.devdocs.json index 41d2c52b9dc61..22b75247b5d5b 100644 --- a/api_docs/dashboard.devdocs.json +++ b/api_docs/dashboard.devdocs.json @@ -728,7 +728,7 @@ "section": "def-common.DashboardPanelMap", "text": "DashboardPanelMap" }, - ", versionOverride?: string | undefined) => ", + ", removeLegacyVersion?: boolean | undefined) => ", "SavedDashboardPanel", "[]" ], @@ -760,12 +760,12 @@ { "parentPluginId": "dashboard", "id": "def-common.convertPanelMapToSavedPanels.$2", - "type": "string", + "type": "CompoundType", "tags": [], - "label": "versionOverride", + "label": "removeLegacyVersion", "description": [], "signature": [ - "string | undefined" + "boolean | undefined" ], "path": "src/plugins/dashboard/common/lib/dashboard_panel_converters.ts", "deprecated": false, @@ -800,7 +800,7 @@ "section": "def-common.SavedObjectEmbeddableInput", "text": "SavedObjectEmbeddableInput" }, - ">, version: string | undefined) => ", + ">, removeLegacyVersion: boolean | undefined) => ", "SavedDashboardPanel" ], "path": "src/plugins/dashboard/common/lib/dashboard_panel_converters.ts", @@ -840,12 +840,12 @@ { "parentPluginId": "dashboard", "id": "def-common.convertPanelStateToSavedDashboardPanel.$2", - "type": "string", + "type": "CompoundType", "tags": [], - "label": "version", + "label": "removeLegacyVersion", "description": [], "signature": [ - "string | undefined" + "boolean | undefined" ], "path": "src/plugins/dashboard/common/lib/dashboard_panel_converters.ts", "deprecated": false, @@ -1761,6 +1761,22 @@ "path": "src/plugins/dashboard/common/dashboard_container/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "dashboard", + "id": "def-common.DashboardPanelState.version", + "type": "string", + "tags": [], + "label": "version", + "description": [ + "\nThis version key was used to store Kibana version information from versions 7.3.0 -> 8.11.0.\nAs of version 8.11.0, the versioning information is now per-embeddable-type and is stored on the\nembeddable's input. This key is needed for BWC, but its value will be removed on Dashboard save." + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/dashboard/common/dashboard_container/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1830,7 +1846,7 @@ "\nFor BWC reasons, dashboard state is stored with panels as an array instead of a map" ], "signature": [ - "{ id?: string | undefined; tags?: string[] | undefined; description?: string | undefined; title?: string | undefined; query?: ", + "{ id?: string | undefined; tags?: string[] | undefined; description?: string | undefined; title?: string | undefined; version?: string | undefined; query?: ", { "pluginId": "@kbn/es-query", "scope": "common", diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index d5fe884018180..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kib | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 100 | 0 | 98 | 9 | +| 101 | 0 | 98 | 9 | ## Client diff --git a/api_docs/dashboard_enhanced.devdocs.json b/api_docs/dashboard_enhanced.devdocs.json index 30c8672eeed00..d4a4e797abcf1 100644 --- a/api_docs/dashboard_enhanced.devdocs.json +++ b/api_docs/dashboard_enhanced.devdocs.json @@ -212,7 +212,7 @@ "label": "getDisplayName", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx", "deprecated": false, diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 5eeb708daf35b..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-22 +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 3076a7d7b395e..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 @@ -8743,22 +8814,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.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": "@kbn/core-saved-objects-api-server-internal", "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/internal_utils.ts" @@ -8771,6 +8826,18 @@ "plugin": "@kbn/core-saved-objects-server-internal", "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, { "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" @@ -8820,20 +8887,8 @@ "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": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, { "plugin": "osquery", @@ -8923,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" @@ -8962,6 +9037,10 @@ { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/packages/get.test.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.test.ts" } ] }, @@ -9048,6 +9127,65 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "data", + "id": "def-public.SavedQuery", + "type": "Interface", + "tags": [], + "label": "SavedQuery", + "description": [], + "path": "src/plugins/data/common/query/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-public.SavedQuery.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "src/plugins/data/common/query/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-public.SavedQuery.attributes", + "type": "Object", + "tags": [], + "label": "attributes", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.SavedQueryAttributes", + "text": "SavedQueryAttributes" + } + ], + "path": "src/plugins/data/common/query/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-public.SavedQuery.namespaces", + "type": "Array", + "tags": [], + "label": "namespaces", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/data/common/query/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "data", "id": "def-public.SearchSourceFields", @@ -11089,13 +11227,10 @@ { "parentPluginId": "data", "id": "def-public.AggGroupLabels.AggGroupNames.Buckets", - "type": "Any", + "type": "string", "tags": [], "label": "[AggGroupNames.Buckets]", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/agg_groups.ts", "deprecated": false, "trackAdoption": false @@ -11103,13 +11238,10 @@ { "parentPluginId": "data", "id": "def-public.AggGroupLabels.AggGroupNames.Metrics", - "type": "Any", + "type": "string", "tags": [], "label": "[AggGroupNames.Metrics]", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/agg_groups.ts", "deprecated": false, "trackAdoption": false @@ -11117,13 +11249,10 @@ { "parentPluginId": "data", "id": "def-public.AggGroupLabels.AggGroupNames.None", - "type": "Any", + "type": "string", "tags": [], "label": "[AggGroupNames.None]", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/agg_groups.ts", "deprecated": false, "trackAdoption": false @@ -11735,7 +11864,7 @@ "label": "intervalOptions", "description": [], "signature": [ - "({ display: any; val: string; enabled(agg: ", + "({ display: string; val: string; enabled(agg: ", { "pluginId": "data", "scope": "common", @@ -11743,7 +11872,7 @@ "section": "def-common.IBucketAggConfig", "text": "IBucketAggConfig" }, - "): boolean; } | { display: any; val: string; })[]" + "): boolean; } | { display: string; val: string; })[]" ], "path": "src/plugins/data/public/index.ts", "deprecated": false, @@ -12052,13 +12181,10 @@ { "parentPluginId": "data", "id": "def-public.search.aggs.parentPipelineType", - "type": "Any", + "type": "string", "tags": [], "label": "parentPipelineType", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/public/index.ts", "deprecated": false, "trackAdoption": false @@ -12161,13 +12287,10 @@ { "parentPluginId": "data", "id": "def-public.search.aggs.siblingPipelineType", - "type": "Any", + "type": "string", "tags": [], "label": "siblingPipelineType", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/public/index.ts", "deprecated": false, "trackAdoption": false @@ -12233,7 +12356,7 @@ "label": "boundsDescendingRaw", "description": [], "signature": [ - "({ bound: number; interval: moment.Duration; boundLabel: any; intervalLabel: any; } | { bound: moment.Duration; interval: moment.Duration; boundLabel: any; intervalLabel: any; })[]" + "({ bound: number; interval: moment.Duration; boundLabel: string; intervalLabel: string; } | { bound: moment.Duration; interval: moment.Duration; boundLabel: string; intervalLabel: string; })[]" ], "path": "src/plugins/data/public/index.ts", "deprecated": false, @@ -12792,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" @@ -12808,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" @@ -13256,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" @@ -13316,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" @@ -13504,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" @@ -13537,44 +13672,116 @@ "path": "packages/kbn-unified-field-list/src/services/field_existing/field_existing_utils.ts" }, { - "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/hooks/use_existing_fields.ts" + }, + { + "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" + }, + { + "plugin": "@kbn/event-annotation-components", + "path": "packages/kbn-event-annotation-components/components/table_list.tsx" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + }, + { + "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": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" }, { - "plugin": "@kbn/event-annotation-components", - "path": "packages/kbn-event-annotation-components/components/group_editor_controls/group_editor_controls.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" }, { - "plugin": "@kbn/event-annotation-components", - "path": "packages/kbn-event-annotation-components/components/table_list.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.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": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.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": "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_management/components/source_selection/source_selection.tsx" }, { "plugin": "ml", @@ -13593,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", @@ -13668,90 +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": "ml", - "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" @@ -13838,23 +13961,23 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "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", @@ -15826,6 +15949,17 @@ "returnComment": [], "children": [] }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.scriptedFieldsEnabled", + "type": "boolean", + "tags": [], + "label": "scriptedFieldsEnabled", + "description": [], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "data", "id": "def-server.DataViewsService.Unnamed", @@ -19155,6 +19289,24 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsServerPluginStart.getScriptedFieldsEnabled", + "type": "Function", + "tags": [], + "label": "getScriptedFieldsEnabled", + "description": [ + "\n" + ], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/data_views/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "initialIsOpen": false @@ -20992,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" @@ -21052,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" @@ -21241,76 +21393,160 @@ "path": "src/plugins/data_views/common/data_views/data_view.ts" }, { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + "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" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "@kbn/unified-field-list", + "path": "packages/kbn-unified-field-list/src/services/field_existing/field_existing_utils.ts" + }, + { + "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/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" + }, + { + "plugin": "@kbn/event-annotation-components", + "path": "packages/kbn-event-annotation-components/components/table_list.tsx" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + }, + { + "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": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "unifiedSearch", - "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "unifiedSearch", - "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "unifiedSearch", - "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_existing/field_existing_utils.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" }, { - "plugin": "@kbn/event-annotation-components", - "path": "packages/kbn-event-annotation-components/components/group_editor_controls/group_editor_controls.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" }, { - "plugin": "@kbn/event-annotation-components", - "path": "packages/kbn-event-annotation-components/components/table_list.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.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": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/rest_api_routes/public/update_data_view.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": "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_management/components/source_selection/source_selection.tsx" }, { "plugin": "ml", @@ -21329,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", @@ -21404,90 +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": "ml", - "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" @@ -21574,23 +21726,23 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "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", @@ -24433,6 +24585,17 @@ "returnComment": [], "children": [] }, + { + "parentPluginId": "data", + "id": "def-common.DataViewsService.scriptedFieldsEnabled", + "type": "boolean", + "tags": [], + "label": "scriptedFieldsEnabled", + "description": [], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "data", "id": "def-common.DataViewsService.Unnamed", @@ -27710,22 +27873,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.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": "@kbn/core-saved-objects-api-server-internal", "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/internal_utils.ts" @@ -27738,6 +27885,18 @@ "plugin": "@kbn/core-saved-objects-server-internal", "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, { "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" @@ -27787,20 +27946,8 @@ "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": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, { "plugin": "osquery", @@ -27890,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" @@ -27929,6 +28096,10 @@ { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/packages/get.test.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.test.ts" } ] }, @@ -28890,6 +29061,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "data", + "id": "def-common.SAVED_QUERY_BASE_URL", + "type": "string", + "tags": [], + "label": "SAVED_QUERY_BASE_URL", + "description": [], + "signature": [ + "\"/internal/saved_query\"" + ], + "path": "src/plugins/data/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "data", "id": "def-common.SCRIPT_LANGUAGES_ROUTE_LATEST_VERSION", diff --git a/api_docs/data.mdx b/api_docs/data.mdx index b2dd5b01cfafd..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 3301 | 119 | 2575 | 27 | +| 3311 | 33 | 2584 | 26 | ## Client diff --git a/api_docs/data_query.devdocs.json b/api_docs/data_query.devdocs.json index 30d5d5a046c8b..68ae04e7173c3 100644 --- a/api_docs/data_query.devdocs.json +++ b/api_docs/data_query.devdocs.json @@ -1471,9 +1471,9 @@ ", { overwrite }?: { overwrite?: boolean | undefined; }) => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ">; updateQuery: (id: string, attributes: ", @@ -1487,33 +1487,33 @@ ") => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ">; getAllSavedQueries: () => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, "[]>; findSavedQueries: (search?: string, perPage?: number, page?: number) => Promise<{ total: number; queries: ", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, "[]; }>; getSavedQuery: (id: string) => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ">; deleteSavedQuery: (id: string) => Promise<{}>; getSavedQueryCount: () => Promise; }" @@ -2851,9 +2851,9 @@ ", { overwrite }?: { overwrite?: boolean | undefined; }) => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ">; updateQuery: (id: string, attributes: ", @@ -2867,33 +2867,33 @@ ") => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ">; getAllSavedQueries: () => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, "[]>; findSavedQueries: (search?: string, perPage?: number, page?: number) => Promise<{ total: number; queries: ", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, "[]; }>; getSavedQuery: (id: string) => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ">; deleteSavedQuery: (id: string) => Promise<{}>; getSavedQueryCount: () => Promise; }" @@ -3041,45 +3041,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "data", - "id": "def-public.SavedQuery", - "type": "Interface", - "tags": [], - "label": "SavedQuery", - "description": [], - "path": "src/plugins/data/public/query/saved_query/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-public.SavedQuery.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "src/plugins/data/public/query/saved_query/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-public.SavedQuery.attributes", - "type": "Object", - "tags": [], - "label": "attributes", - "description": [], - "signature": [ - "SavedQueryAttributes" - ], - "path": "src/plugins/data/public/query/saved_query/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "data", "id": "def-public.SavedQueryService", @@ -3100,13 +3061,19 @@ "description": [], "signature": [ "(attributes: ", - "SavedQueryAttributes", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.SavedQueryAttributes", + "text": "SavedQueryAttributes" + }, ") => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ">" @@ -3123,7 +3090,13 @@ "label": "attributes", "description": [], "signature": [ - "SavedQueryAttributes" + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.SavedQueryAttributes", + "text": "SavedQueryAttributes" + } ], "path": "src/plugins/data/public/query/saved_query/types.ts", "deprecated": false, @@ -3142,13 +3115,19 @@ "description": [], "signature": [ "(id: string, attributes: ", - "SavedQueryAttributes", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.SavedQueryAttributes", + "text": "SavedQueryAttributes" + }, ") => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ">" @@ -3180,7 +3159,13 @@ "label": "attributes", "description": [], "signature": [ - "SavedQueryAttributes" + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.SavedQueryAttributes", + "text": "SavedQueryAttributes" + } ], "path": "src/plugins/data/public/query/saved_query/types.ts", "deprecated": false, @@ -3201,9 +3186,9 @@ "() => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, "[]>" @@ -3225,9 +3210,9 @@ "(searchText?: string | undefined, perPage?: number | undefined, activePage?: number | undefined) => Promise<{ total: number; queries: ", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, "[]; }>" @@ -3295,9 +3280,9 @@ "(id: string) => Promise<", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ">" @@ -4660,6 +4645,20 @@ "path": "src/plugins/data/common/query/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-common.SavedQuery.namespaces", + "type": "Array", + "tags": [], + "label": "namespaces", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/data/common/query/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index cb8d5837f20c3..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 3301 | 119 | 2575 | 27 | +| 3311 | 33 | 2584 | 26 | ## Client diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index d8398694e33df..ceb9136800672 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -1412,15 +1412,12 @@ { "parentPluginId": "data", "id": "def-public.noSearchSessionStorageCapabilityMessage", - "type": "Any", + "type": "string", "tags": [], "label": "noSearchSessionStorageCapabilityMessage", "description": [ "\nMessage to display in case storing\nsession session is disabled due to turned off capability" ], - "signature": [ - "any" - ], "path": "src/plugins/data/public/search/session/i18n.ts", "deprecated": false, "trackAdoption": false, @@ -30239,6 +30236,17 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "data", + "id": "def-common.SearchSourceDependencies.scriptedFieldsEnabled", + "type": "boolean", + "tags": [], + "label": "scriptedFieldsEnabled", + "description": [], + "path": "src/plugins/data/common/search/search_source/search_source.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -32092,7 +32100,7 @@ "label": "boundsDescendingRaw", "description": [], "signature": [ - "({ bound: number; interval: moment.Duration; boundLabel: any; intervalLabel: any; } | { bound: moment.Duration; interval: moment.Duration; boundLabel: any; intervalLabel: any; })[]" + "({ bound: number; interval: moment.Duration; boundLabel: string; intervalLabel: string; } | { bound: moment.Duration; interval: moment.Duration; boundLabel: string; intervalLabel: string; })[]" ], "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/calc_auto_interval.ts", "deprecated": false, @@ -32449,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", @@ -34193,7 +34216,7 @@ "label": "intervalOptions", "description": [], "signature": [ - "({ display: any; val: string; enabled(agg: ", + "({ display: string; val: string; enabled(agg: ", { "pluginId": "data", "scope": "common", @@ -34201,7 +34224,7 @@ "section": "def-common.IBucketAggConfig", "text": "IBucketAggConfig" }, - "): boolean; } | { display: any; val: string; })[]" + "): boolean; } | { display: string; val: string; })[]" ], "path": "src/plugins/data/common/search/aggs/buckets/_interval_options.ts", "deprecated": false, @@ -34962,13 +34985,10 @@ { "parentPluginId": "data", "id": "def-common.parentPipelineType", - "type": "Any", + "type": "string", "tags": [], "label": "parentPipelineType", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts", "deprecated": false, "trackAdoption": false, @@ -35220,13 +35240,10 @@ { "parentPluginId": "data", "id": "def-common.siblingPipelineType", - "type": "Any", + "type": "string", "tags": [], "label": "siblingPipelineType", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts", "deprecated": false, "trackAdoption": false, @@ -35373,13 +35390,10 @@ { "parentPluginId": "data", "id": "def-common.AggGroupLabels.AggGroupNames.Buckets", - "type": "Any", + "type": "string", "tags": [], "label": "[AggGroupNames.Buckets]", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/agg_groups.ts", "deprecated": false, "trackAdoption": false @@ -35387,13 +35401,10 @@ { "parentPluginId": "data", "id": "def-common.AggGroupLabels.AggGroupNames.Metrics", - "type": "Any", + "type": "string", "tags": [], "label": "[AggGroupNames.Metrics]", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/agg_groups.ts", "deprecated": false, "trackAdoption": false @@ -35401,13 +35412,10 @@ { "parentPluginId": "data", "id": "def-common.AggGroupLabels.AggGroupNames.None", - "type": "Any", + "type": "string", "tags": [], "label": "[AggGroupNames.None]", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/agg_groups.ts", "deprecated": false, "trackAdoption": false @@ -35486,13 +35494,10 @@ { "parentPluginId": "data", "id": "def-common.cidrFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/cidr.ts", "deprecated": false, "trackAdoption": false @@ -35550,13 +35555,10 @@ { "parentPluginId": "data", "id": "def-common.cidrFunction.args.mask.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/cidr.ts", "deprecated": false, "trackAdoption": false @@ -35685,13 +35687,10 @@ { "parentPluginId": "data", "id": "def-common.dateRangeFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/date_range.ts", "deprecated": false, "trackAdoption": false @@ -35735,13 +35734,10 @@ { "parentPluginId": "data", "id": "def-common.dateRangeFunction.args.from.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/date_range.ts", "deprecated": false, "trackAdoption": false @@ -35776,13 +35772,10 @@ { "parentPluginId": "data", "id": "def-common.dateRangeFunction.args.to.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/date_range.ts", "deprecated": false, "trackAdoption": false @@ -36086,13 +36079,10 @@ { "parentPluginId": "data", "id": "def-common.existsFilterFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/exists_filter.ts", "deprecated": false, "trackAdoption": false @@ -36150,13 +36140,10 @@ { "parentPluginId": "data", "id": "def-common.existsFilterFunction.args.field.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/exists_filter.ts", "deprecated": false, "trackAdoption": false @@ -36205,13 +36192,10 @@ { "parentPluginId": "data", "id": "def-common.existsFilterFunction.args.negate.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/exists_filter.ts", "deprecated": false, "trackAdoption": false @@ -36342,13 +36326,10 @@ { "parentPluginId": "data", "id": "def-common.extendedBoundsFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/extended_bounds.ts", "deprecated": false, "trackAdoption": false @@ -36392,13 +36373,10 @@ { "parentPluginId": "data", "id": "def-common.extendedBoundsFunction.args.min.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/extended_bounds.ts", "deprecated": false, "trackAdoption": false @@ -36433,13 +36411,10 @@ { "parentPluginId": "data", "id": "def-common.extendedBoundsFunction.args.max.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/extended_bounds.ts", "deprecated": false, "trackAdoption": false @@ -36568,13 +36543,10 @@ { "parentPluginId": "data", "id": "def-common.fieldFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/field.ts", "deprecated": false, "trackAdoption": false @@ -36632,13 +36604,10 @@ { "parentPluginId": "data", "id": "def-common.fieldFunction.args.name.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/field.ts", "deprecated": false, "trackAdoption": false @@ -36687,13 +36656,10 @@ { "parentPluginId": "data", "id": "def-common.fieldFunction.args.type.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/field.ts", "deprecated": false, "trackAdoption": false @@ -36728,13 +36694,10 @@ { "parentPluginId": "data", "id": "def-common.fieldFunction.args.script.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/field.ts", "deprecated": false, "trackAdoption": false @@ -36856,13 +36819,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -36906,13 +36866,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.args.top.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -36947,13 +36904,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.args.left.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -36988,13 +36942,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.args.bottom.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -37029,13 +36980,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.args.right.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -37070,13 +37018,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.args.wkt.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -37111,13 +37056,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.args.topLeft.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -37152,13 +37094,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.args.bottomRight.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -37193,13 +37132,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.args.topRight.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -37234,13 +37170,10 @@ { "parentPluginId": "data", "id": "def-common.geoBoundingBoxFunction.args.bottomLeft.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_bounding_box.ts", "deprecated": false, "trackAdoption": false @@ -37362,13 +37295,10 @@ { "parentPluginId": "data", "id": "def-common.geoPointFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_point.ts", "deprecated": false, "trackAdoption": false @@ -37412,13 +37342,10 @@ { "parentPluginId": "data", "id": "def-common.geoPointFunction.args.lat.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_point.ts", "deprecated": false, "trackAdoption": false @@ -37453,13 +37380,10 @@ { "parentPluginId": "data", "id": "def-common.geoPointFunction.args.lon.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_point.ts", "deprecated": false, "trackAdoption": false @@ -37522,13 +37446,10 @@ { "parentPluginId": "data", "id": "def-common.geoPointFunction.args.point.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/geo_point.ts", "deprecated": false, "trackAdoption": false @@ -37650,13 +37571,10 @@ { "parentPluginId": "data", "id": "def-common.ipRangeFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/ip_range.ts", "deprecated": false, "trackAdoption": false @@ -37714,13 +37632,10 @@ { "parentPluginId": "data", "id": "def-common.ipRangeFunction.args.from.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/ip_range.ts", "deprecated": false, "trackAdoption": false @@ -37769,13 +37684,10 @@ { "parentPluginId": "data", "id": "def-common.ipRangeFunction.args.to.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/ip_range.ts", "deprecated": false, "trackAdoption": false @@ -37904,13 +37816,10 @@ { "parentPluginId": "data", "id": "def-common.kibana.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/kibana.ts", "deprecated": false, "trackAdoption": false @@ -38117,13 +38026,10 @@ { "parentPluginId": "data", "id": "def-common.kibanaFilterFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/kibana_filter.ts", "deprecated": false, "trackAdoption": false @@ -38195,13 +38101,10 @@ { "parentPluginId": "data", "id": "def-common.kibanaFilterFunction.args.query.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/kibana_filter.ts", "deprecated": false, "trackAdoption": false @@ -38250,13 +38153,10 @@ { "parentPluginId": "data", "id": "def-common.kibanaFilterFunction.args.negate.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/kibana_filter.ts", "deprecated": false, "trackAdoption": false @@ -38305,13 +38205,10 @@ { "parentPluginId": "data", "id": "def-common.kibanaFilterFunction.args.disabled.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/kibana_filter.ts", "deprecated": false, "trackAdoption": false @@ -38426,13 +38323,10 @@ { "parentPluginId": "data", "id": "def-common.kibanaTimerangeFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/timerange.ts", "deprecated": false, "trackAdoption": false @@ -38490,13 +38384,10 @@ { "parentPluginId": "data", "id": "def-common.kibanaTimerangeFunction.args.from.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/timerange.ts", "deprecated": false, "trackAdoption": false @@ -38545,13 +38436,10 @@ { "parentPluginId": "data", "id": "def-common.kibanaTimerangeFunction.args.to.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/timerange.ts", "deprecated": false, "trackAdoption": false @@ -38600,13 +38488,10 @@ { "parentPluginId": "data", "id": "def-common.kibanaTimerangeFunction.args.mode.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/timerange.ts", "deprecated": false, "trackAdoption": false @@ -38735,13 +38620,10 @@ { "parentPluginId": "data", "id": "def-common.kqlFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/kql.ts", "deprecated": false, "trackAdoption": false @@ -38813,13 +38695,10 @@ { "parentPluginId": "data", "id": "def-common.kqlFunction.args.q.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/kql.ts", "deprecated": false, "trackAdoption": false @@ -38934,13 +38813,10 @@ { "parentPluginId": "data", "id": "def-common.luceneFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/lucene.ts", "deprecated": false, "trackAdoption": false @@ -39012,13 +38888,10 @@ { "parentPluginId": "data", "id": "def-common.luceneFunction.args.q.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/lucene.ts", "deprecated": false, "trackAdoption": false @@ -39276,13 +39149,10 @@ { "parentPluginId": "data", "id": "def-common.numericalRangeFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/numerical_range.ts", "deprecated": false, "trackAdoption": false @@ -39326,13 +39196,10 @@ { "parentPluginId": "data", "id": "def-common.numericalRangeFunction.args.from.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/numerical_range.ts", "deprecated": false, "trackAdoption": false @@ -39367,13 +39234,10 @@ { "parentPluginId": "data", "id": "def-common.numericalRangeFunction.args.to.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/numerical_range.ts", "deprecated": false, "trackAdoption": false @@ -39408,13 +39272,10 @@ { "parentPluginId": "data", "id": "def-common.numericalRangeFunction.args.label.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/numerical_range.ts", "deprecated": false, "trackAdoption": false @@ -39501,13 +39362,10 @@ { "parentPluginId": "data", "id": "def-common.parentPipelineAggHelper.subtype", - "type": "Any", + "type": "string", "tags": [], "label": "subtype", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts", "deprecated": false, "trackAdoption": false @@ -39649,13 +39507,10 @@ { "parentPluginId": "data", "id": "def-common.phraseFilterFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/phrase_filter.ts", "deprecated": false, "trackAdoption": false @@ -39713,13 +39568,10 @@ { "parentPluginId": "data", "id": "def-common.phraseFilterFunction.args.field.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/phrase_filter.ts", "deprecated": false, "trackAdoption": false @@ -39782,13 +39634,10 @@ { "parentPluginId": "data", "id": "def-common.phraseFilterFunction.args.phrase.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/phrase_filter.ts", "deprecated": false, "trackAdoption": false @@ -39837,13 +39686,10 @@ { "parentPluginId": "data", "id": "def-common.phraseFilterFunction.args.negate.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/phrase_filter.ts", "deprecated": false, "trackAdoption": false @@ -39974,13 +39820,10 @@ { "parentPluginId": "data", "id": "def-common.queryFilterFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/query_filter.ts", "deprecated": false, "trackAdoption": false @@ -40052,13 +39895,10 @@ { "parentPluginId": "data", "id": "def-common.queryFilterFunction.args.input.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/query_filter.ts", "deprecated": false, "trackAdoption": false @@ -40093,13 +39933,10 @@ { "parentPluginId": "data", "id": "def-common.queryFilterFunction.args.label.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/query_filter.ts", "deprecated": false, "trackAdoption": false @@ -40221,13 +40058,10 @@ { "parentPluginId": "data", "id": "def-common.rangeFilterFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/range_filter.ts", "deprecated": false, "trackAdoption": false @@ -40285,13 +40119,10 @@ { "parentPluginId": "data", "id": "def-common.rangeFilterFunction.args.field.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/range_filter.ts", "deprecated": false, "trackAdoption": false @@ -40340,13 +40171,10 @@ { "parentPluginId": "data", "id": "def-common.rangeFilterFunction.args.range.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/range_filter.ts", "deprecated": false, "trackAdoption": false @@ -40395,13 +40223,10 @@ { "parentPluginId": "data", "id": "def-common.rangeFilterFunction.args.negate.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/range_filter.ts", "deprecated": false, "trackAdoption": false @@ -40532,13 +40357,10 @@ { "parentPluginId": "data", "id": "def-common.rangeFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/range.ts", "deprecated": false, "trackAdoption": false @@ -40582,13 +40404,10 @@ { "parentPluginId": "data", "id": "def-common.rangeFunction.args.gt.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/range.ts", "deprecated": false, "trackAdoption": false @@ -40623,13 +40442,10 @@ { "parentPluginId": "data", "id": "def-common.rangeFunction.args.lt.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/range.ts", "deprecated": false, "trackAdoption": false @@ -40664,13 +40480,10 @@ { "parentPluginId": "data", "id": "def-common.rangeFunction.args.gte.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/range.ts", "deprecated": false, "trackAdoption": false @@ -40705,13 +40518,10 @@ { "parentPluginId": "data", "id": "def-common.rangeFunction.args.lte.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/range.ts", "deprecated": false, "trackAdoption": false @@ -40841,13 +40651,10 @@ { "parentPluginId": "data", "id": "def-common.removeFilterFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/remove_filter.ts", "deprecated": false, "trackAdoption": false @@ -40905,13 +40712,10 @@ { "parentPluginId": "data", "id": "def-common.removeFilterFunction.args.group.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/remove_filter.ts", "deprecated": false, "trackAdoption": false @@ -40946,13 +40750,10 @@ { "parentPluginId": "data", "id": "def-common.removeFilterFunction.args.from.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/remove_filter.ts", "deprecated": false, "trackAdoption": false @@ -41015,13 +40816,10 @@ { "parentPluginId": "data", "id": "def-common.removeFilterFunction.args.ungrouped.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/remove_filter.ts", "deprecated": false, "trackAdoption": false @@ -41182,13 +40980,10 @@ { "parentPluginId": "data", "id": "def-common.selectFilterFunction.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/select_filter.ts", "deprecated": false, "trackAdoption": false @@ -41246,13 +41041,10 @@ { "parentPluginId": "data", "id": "def-common.selectFilterFunction.args.group.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/select_filter.ts", "deprecated": false, "trackAdoption": false @@ -41301,13 +41093,10 @@ { "parentPluginId": "data", "id": "def-common.selectFilterFunction.args.from.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/select_filter.ts", "deprecated": false, "trackAdoption": false @@ -41370,13 +41159,10 @@ { "parentPluginId": "data", "id": "def-common.selectFilterFunction.args.ungrouped.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/expressions/select_filter.ts", "deprecated": false, "trackAdoption": false @@ -41495,13 +41281,10 @@ { "parentPluginId": "data", "id": "def-common.siblingPipelineAggHelper.subtype", - "type": "Any", + "type": "string", "tags": [], "label": "subtype", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/data/common/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index f9b12d448d526..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 3301 | 119 | 2575 | 27 | +| 3311 | 33 | 2584 | 26 | ## Client diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index f982d68f11caa..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-22 +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.devdocs.json b/api_docs/data_view_field_editor.devdocs.json index d4916b3da0d34..b961c3f8fa265 100644 --- a/api_docs/data_view_field_editor.devdocs.json +++ b/api_docs/data_view_field_editor.devdocs.json @@ -95,7 +95,7 @@ "section": "def-public.FormatEditorState", "text": "FormatEditorState" }, - ") => { error: any; samples: ", + ") => { error: string | undefined; samples: ", { "pluginId": "dataViewFieldEditor", "scope": "public", diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 0bc783a2ff599..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-22 +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 1dba864cec118..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-22 +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 7da5deb550cc2..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" @@ -388,180 +392,176 @@ "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.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/server/models/job_service/new_job_caps/rollup.ts" + "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/server/lib/alerts/alerting_service.ts" + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" }, { "plugin": "ml", - "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" + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "visTypeTimeseries", - "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "visTypeTimeseries", - "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "visTypeTimeseries", - "path": "src/plugins/vis_types/timeseries/server/lib/get_fields.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "apm", - "path": "x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "exploratoryView", - "path": "x-pack/plugins/exploratory_view/public/utils/observability_data_views/observability_data_views.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "exploratoryView", - "path": "x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "exploratoryView", - "path": "x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/use_filter_values.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" }, { - "plugin": "exploratoryView", - "path": "x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" }, { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" }, { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/entity_index_expression.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" }, { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" + "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": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" }, { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" }, { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" }, { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" }, { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts" }, { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.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/server/lib/alerts/alerting_service.ts" }, { "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/get_fields.ts" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + "plugin": "apm", + "path": "x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + "plugin": "exploratoryView", + "path": "x-pack/plugins/exploratory_view/public/utils/observability_data_views/observability_data_views.ts" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + "plugin": "exploratoryView", + "path": "x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + "plugin": "exploratoryView", + "path": "x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/use_filter_values.ts" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + "plugin": "exploratoryView", + "path": "x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/entity_index_expression.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" }, { - "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": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/index.tsx" }, { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx" }, { "plugin": "infra", @@ -649,23 +649,23 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "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", @@ -3667,6 +3667,45 @@ "deprecated": false, "trackAdoption": false, "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewsPublicPlugin.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "src/plugins/data_views/public/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewsPublicPlugin.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "initializerContext", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-plugins-browser", + "scope": "common", + "docId": "kibKbnCorePluginsBrowserPluginApi", + "section": "def-common.PluginInitializerContext", + "text": "PluginInitializerContext" + }, + "" + ], + "path": "src/plugins/data_views/public/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "dataViews", "id": "def-public.DataViewsPublicPlugin.setup", @@ -3914,6 +3953,17 @@ "returnComment": [], "children": [] }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewsService.scriptedFieldsEnabled", + "type": "boolean", + "tags": [], + "label": "scriptedFieldsEnabled", + "description": [], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "dataViews", "id": "def-public.DataViewsService.Unnamed", @@ -5474,6 +5524,17 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewsServicePublic.scriptedFieldsEnabled", + "type": "boolean", + "tags": [], + "label": "scriptedFieldsEnabled", + "description": [], + "path": "src/plugins/data_views/public/data_views_service_public.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "dataViews", "id": "def-public.DataViewsServicePublic.Unnamed", @@ -6488,6 +6549,17 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewsServicePublicDeps.scriptedFieldsEnabled", + "type": "boolean", + "tags": [], + "label": "scriptedFieldsEnabled", + "description": [], + "path": "src/plugins/data_views/public/data_views_service_public.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -7963,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" @@ -8023,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" @@ -8195,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" @@ -8205,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", @@ -8232,52 +8308,132 @@ "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" }, { - "plugin": "unifiedSearch", - "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "@kbn/unified-field-list", + "path": "packages/kbn-unified-field-list/src/services/field_existing/field_existing_utils.ts" + }, + { + "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/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" + }, + { + "plugin": "@kbn/event-annotation-components", + "path": "packages/kbn-event-annotation-components/components/table_list.tsx" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + }, + { + "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": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_existing/field_existing_utils.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" }, { - "plugin": "@kbn/event-annotation-components", - "path": "packages/kbn-event-annotation-components/components/group_editor_controls/group_editor_controls.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" }, { - "plugin": "@kbn/event-annotation-components", - "path": "packages/kbn-event-annotation-components/components/table_list.tsx" + "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": "lens", - "path": "x-pack/plugins/lens/public/data_views_service/loader.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": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.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_management/components/source_selection/source_selection.tsx" }, { "plugin": "ml", @@ -8296,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", @@ -8371,90 +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": "ml", - "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" @@ -8541,23 +8613,23 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "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", @@ -10746,7 +10818,7 @@ "section": "def-common.DataViewsService", "text": "DataViewsService" }, - ">; }" + ">; getScriptedFieldsEnabled: () => boolean; }" ], "path": "src/plugins/data_views/server/plugin.ts", "deprecated": false, @@ -10847,6 +10919,17 @@ "returnComment": [], "children": [] }, + { + "parentPluginId": "dataViews", + "id": "def-server.DataViewsService.scriptedFieldsEnabled", + "type": "boolean", + "tags": [], + "label": "scriptedFieldsEnabled", + "description": [], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "dataViews", "id": "def-server.DataViewsService.Unnamed", @@ -14931,6 +15014,24 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "dataViews", + "id": "def-server.DataViewsServerPluginStart.getScriptedFieldsEnabled", + "type": "Function", + "tags": [], + "label": "getScriptedFieldsEnabled", + "description": [ + "\n" + ], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/data_views/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "lifecycle": "start", @@ -15008,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" @@ -15068,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" @@ -15240,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" @@ -15248,81 +15353,161 @@ "plugin": "data", "path": "src/plugins/data/common/search/tabify/response_writer.ts" }, + { + "plugin": "data", + "path": "src/plugins/data/public/search/errors/painless_error.tsx" + }, { "plugin": "data", "path": "src/plugins/data/common/search/aggs/param_types/field.ts" }, { - "plugin": "data", - "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" + "plugin": "logsShared", + "path": "x-pack/plugins/logs_shared/common/log_views/resolved_log_view.ts" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "@kbn/unified-field-list", + "path": "packages/kbn-unified-field-list/src/services/field_existing/field_existing_utils.ts" + }, + { + "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/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" + }, + { + "plugin": "@kbn/event-annotation-components", + "path": "packages/kbn-event-annotation-components/components/table_list.tsx" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + }, + { + "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": "data", - "path": "src/plugins/data/public/search/errors/painless_error.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "unifiedSearch", - "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "plugin": "unifiedSearch", - "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "unifiedSearch", - "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_existing/field_existing_utils.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" }, { - "plugin": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/hooks/use_existing_fields.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" }, { - "plugin": "@kbn/event-annotation-components", - "path": "packages/kbn-event-annotation-components/components/group_editor_controls/group_editor_controls.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" }, { - "plugin": "@kbn/event-annotation-components", - "path": "packages/kbn-event-annotation-components/components/table_list.tsx" + "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": "lens", - "path": "x-pack/plugins/lens/public/data_views_service/loader.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": "@kbn/unified-field-list", - "path": "packages/kbn-unified-field-list/src/services/field_stats/load_field_stats.ts" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.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_management/components/source_selection/source_selection.tsx" }, { "plugin": "ml", @@ -15341,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", @@ -15416,90 +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": "ml", - "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" @@ -15586,23 +15687,23 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx" + "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", @@ -18556,6 +18657,17 @@ "returnComment": [], "children": [] }, + { + "parentPluginId": "dataViews", + "id": "def-common.DataViewsService.scriptedFieldsEnabled", + "type": "boolean", + "tags": [], + "label": "scriptedFieldsEnabled", + "description": [], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "dataViews", "id": "def-common.DataViewsService.Unnamed", @@ -21225,6 +21337,17 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-common.DataViewsServiceDeps.scriptedFieldsEnabled", + "type": "boolean", + "tags": [], + "label": "scriptedFieldsEnabled", + "description": [], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -24254,22 +24377,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.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": "@kbn/core-saved-objects-api-server-internal", "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/internal_utils.ts" @@ -24282,6 +24389,18 @@ "plugin": "@kbn/core-saved-objects-server-internal", "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, { "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" @@ -24331,20 +24450,8 @@ "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": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, { "plugin": "osquery", @@ -24434,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" @@ -24473,6 +24600,10 @@ { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/packages/get.test.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.test.ts" } ] }, diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index ddafd97db27cc..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1024 | 0 | 246 | 2 | +| 1034 | 0 | 254 | 2 | ## Client diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 7ce6cb745989c..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-22 +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 720a95ed2dd6c..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -16,39 +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 | - | -| | inspector, data, savedObjects, dataViewEditor, unifiedSearch, embeddable, visualizations, controls, dashboard, licensing, savedObjectsTagging, eventAnnotation, dataViewFieldEditor, lens, security, triggersActionsUi, cases, @kbn/ml-date-picker, aiops, observabilityShared, exploratoryView, fleet, observability, telemetry, advancedSettings, maps, dataVisualizer, ml, banners, reporting, timelines, cloudSecurityPosture, runtimeFields, indexManagement, dashboardEnhanced, imageEmbeddable, graph, monitoring, securitySolution, synthetics, transform, uptime, cloudLinks, console, dataViewManagement, filesManagement, uiActions, visTypeVislib | - | -| | home, data, esUiShared, savedObjectsManagement, exploratoryView, fleet, observability, ml, apm, indexLifecycleManagement, observabilityOnboarding, synthetics, upgradeAssistant, uptime, ux, kibanaOverview | - | -| | share, uiActions, guidedOnboarding, home, management, spaces, savedObjects, serverless, visualizations, controls, 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, savedObjects, embeddable, visualizations, canvas, graph, ml, @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 | - | -| | observability, @kbn/securitysolution-data-table, securitySolution | - | -| | @kbn/core-plugins-browser-internal, @kbn/core-root-browser-internal, home, savedObjects, unifiedSearch, presentationUtil, visualizations, fileUpload, dashboardEnhanced, transform, discover, observability, dataVisualizer | - | -| | @kbn/core-saved-objects-browser-mocks, savedObjects, presentationUtil, observability, dashboardEnhanced, @kbn/core-saved-objects-browser-internal | - | -| | monitoring | - | | | alerting, discover, securitySolution | - | -| | @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-api-server-internal, @kbn/core-saved-objects-import-export-server-internal, @kbn/core-saved-objects-server-internal, home, fleet, graph, lists, osquery, securitySolution, alerting | - | -| | @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-api-server-internal, @kbn/core-saved-objects-import-export-server-internal, @kbn/core-saved-objects-server-internal, home, 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-saved-objects-api-server, @kbn/core, home, savedObjectsTagging, canvas, savedObjects, @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-import-export-server-internal, savedObjectsTaggingOss, lists, securitySolution, upgradeAssistant, savedObjectsManagement, @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 | - | @@ -61,20 +58,26 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | securitySolution | - | | | securitySolution | - | | | securitySolution | - | -| | exploratoryView, fleet, dataVisualizer, cloudSecurityPosture, discoverEnhanced, osquery, synthetics | - | -| | @kbn/core-lifecycle-browser, @kbn/core-saved-objects-browser-internal, @kbn/core, visualizations, exploratoryView, transform, @kbn/core-saved-objects-browser-mocks | - | +| | 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 | - | | | discover | - | | | data, discover, imageEmbeddable, embeddable | - | | | @kbn/core-saved-objects-browser-mocks, discover, @kbn/core-saved-objects-browser-internal | - | | | advancedSettings, discover | - | -| | @kbn/core-saved-objects-api-browser, @kbn/core, savedObjects, savedObjectsManagement, visualizations, savedObjectsTagging, eventAnnotation, lens, graph, dashboard, savedObjectsTaggingOss, kibanaUtils, expressions, data, embeddable, controls, uiActionsEnhanced, maps, canvas, dashboardEnhanced, globalSearchProviders | - | +| | @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, 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, @kbn/core-saved-objects-browser-mocks, savedObjects | - | -| | @kbn/core-saved-objects-browser-mocks, home, @kbn/core-saved-objects-browser-internal | - | -| | @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-browser-mocks, savedObjects, visualizations | - | +| | @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, visualizations, @kbn/core-saved-objects-browser-mocks | - | | | @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-browser-internal | - | -| | @kbn/core-saved-objects-browser-mocks, savedObjects, dashboardEnhanced, @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 | - | | | @kbn/core-saved-objects-browser-mocks, savedObjects, @kbn/core-saved-objects-browser-internal | - | | | @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-browser-internal | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-browser-mocks, savedObjects | - | @@ -83,22 +86,18 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | @kbn/core-saved-objects-browser-internal | - | | | @kbn/core-saved-objects-browser-internal | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core, savedObjects, visualizations, graph | - | -| | @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-api-server-internal, canvas | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core | - | -| | @kbn/core-saved-objects-browser-internal, @kbn/core, spaces, savedSearch, visualizations, lens, cases, maps, canvas, graph | - | +| | @kbn/core-saved-objects-browser-internal, @kbn/core, cases, spaces, savedSearch, visualizations, lens, maps, canvas, graph | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core | - | | | @kbn/core-saved-objects-browser-internal | - | -| | @kbn/core-root-browser-internal, @kbn/core-saved-objects-browser-mocks | - | -| | @kbn/core-saved-objects-api-server-internal | - | -| | @kbn/core-saved-objects-api-server-internal, fleet | - | -| | @kbn/core-saved-objects-server-internal, @kbn/core-plugins-server-internal, savedObjectsTagging, @kbn/core-saved-objects-server-mocks | - | | | home, osquery | - | +| | @kbn/core-root-browser-internal, @kbn/core-saved-objects-browser-mocks | - | | | visTypeTimeseries, graph, dataViewManagement, dataViews | - | | | visTypeTimeseries, graph, dataViewManagement, dataViews | - | | | visTypeTimeseries, graph, dataViewManagement | - | @@ -141,13 +140,13 @@ 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 | | | embeddable, presentationUtil, dashboard, lens, discover, graph | 8.8.0 | -| | @kbn/core-application-browser-internal, @kbn/core-application-browser-mocks, management, fleet, security, kibanaOverview, @kbn/core | 8.8.0 | +| | @kbn/core-application-browser-internal, management, @kbn/core-application-browser-mocks, fleet, security, kibanaOverview, @kbn/core | 8.8.0 | | | apm | 8.8.0 | | | security | 8.8.0 | | | mapsEms | 8.8.0 | @@ -189,6 +188,7 @@ Safe to remove. | | expressions | | | expressions | | | expressions | +| | home | | | kibanaReact | | | kibanaReact | | | kibanaReact | @@ -196,6 +196,10 @@ Safe to remove. | | licensing | | | licensing | | | licensing | +| | lists | +| | lists | +| | lists | +| | lists | | | reporting | | | reporting | | | reporting | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index ee36712c5326a..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -40,14 +40,14 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectsBulkUpdateOptions) | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectsBulkResolveResponse) | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectsBulkCreateObject) | - | -| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/server/index.ts#:~:text=SavedObjectAttributes), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectAttributes), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObjectAttributes), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/server/index.ts#:~:text=SavedObjectAttributes) | - | -| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectsStart), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/server/index.ts#:~:text=SavedObjectsStart) | - | +| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/server/index.ts#:~:text=SavedObjectAttributes), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObjectAttributes), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectAttributes), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/server/index.ts#:~:text=SavedObjectAttributes) | - | +| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/server/index.ts#:~:text=SavedObjectsStart), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectsStart) | - | | | [mocks.ts](https://github.com/elastic/kibana/tree/main/src/core/public/mocks.ts#:~:text=savedObjectsServiceMock) | - | | | [mocks.ts](https://github.com/elastic/kibana/tree/main/src/core/public/mocks.ts#:~:text=simpleSavedObjectMock) | - | -| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObject) | - | -| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectAttributeSingle), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObjectAttributeSingle) | - | -| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectAttribute), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObjectAttribute) | - | -| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectReference), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObjectReference) | - | +| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObject) | - | +| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObjectAttributeSingle), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectAttributeSingle) | - | +| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObjectAttribute), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectAttribute) | - | +| | [index.ts](https://github.com/elastic/kibana/tree/main/src/core/types/index.ts#:~:text=SavedObjectReference), [index.ts](https://github.com/elastic/kibana/tree/main/src/core/public/index.ts#:~:text=SavedObjectReference) | - | @@ -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) | - | @@ -314,14 +304,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] -## @kbn/ml-date-picker - -| Deprecated API | Reference location(s) | Remove By | -| ---------------|-----------|-----------| -| | [use_date_picker_context.tsx](https://github.com/elastic/kibana/tree/main/x-pack/packages/ml/date_picker/src/hooks/use_date_picker_context.tsx#:~:text=toMountPoint) | - | - - - ## @kbn/react-kibana-context-styled | Deprecated API | Reference location(s) | Remove By | @@ -379,7 +361,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/plugin.ts#:~:text=authc) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/plugin.ts#:~:text=authz) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/plugin.ts#:~:text=index) | - | -| | [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/types.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/types.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/types.ts#:~:text=SavedObjectAttributes)+ 10 more | - | +| | [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client/actions_client.ts#:~:text=SavedObjectAttributes), [actions_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/actions_client/actions_client.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/types.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/types.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/types.ts#:~:text=SavedObjectAttributes)+ 10 more | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/saved_objects/index.ts#:~:text=convertToMultiNamespaceTypeVersion), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/server/saved_objects/index.ts#:~:text=convertToMultiNamespaceTypeVersion) | - | @@ -399,7 +381,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [embeddable_change_point_chart.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx#:~:text=toMountPoint), [embeddable_change_point_chart.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx#:~:text=toMountPoint), [log_categorization_app_state.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx#:~:text=toMountPoint), [log_categorization_app_state.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx#:~:text=toMountPoint), [show_flyout.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx#:~:text=toMountPoint), [show_flyout.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx#:~:text=toMountPoint), [show_flyout.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx#:~:text=toMountPoint), [log_rate_analysis_app_state.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_app_state.tsx#:~:text=toMountPoint), [log_rate_analysis_app_state.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_app_state.tsx#:~:text=toMountPoint), [log_rate_analysis_content_wrapper.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx#:~:text=toMountPoint)+ 3 more | - | | | [embeddable_change_point_chart.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx#:~:text=KibanaThemeProvider), [embeddable_change_point_chart.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx#:~:text=KibanaThemeProvider), [embeddable_change_point_chart.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx#:~:text=KibanaThemeProvider) | - | | | [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/plugin.tsx#:~:text=license%24) | 8.8.0 | | | [search_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/application/utils/search_utils.ts#:~:text=SimpleSavedObject), [search_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/application/utils/search_utils.ts#:~:text=SimpleSavedObject) | - | @@ -581,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) | - | @@ -656,7 +637,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title) | - | | | [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title) | - | | | [results_links.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx#:~:text=indexPatternId), [actions_panel.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx#:~:text=indexPatternId) | - | -| | [grid_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx#:~:text=toMountPoint), [grid_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx#:~:text=toMountPoint), [index_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx#:~:text=toMountPoint), [index_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx#:~:text=toMountPoint), [data_comparison_app_state.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/data_comparison/data_comparison_app_state.tsx#:~:text=toMountPoint), [data_comparison_app_state.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/data_comparison/data_comparison_app_state.tsx#:~:text=toMountPoint) | - | | | [file_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx#:~:text=KibanaThemeProvider), [file_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx#:~:text=KibanaThemeProvider), [file_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx#:~:text=KibanaThemeProvider), [grid_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx#:~:text=KibanaThemeProvider), [grid_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx#:~:text=KibanaThemeProvider), [grid_embeddable.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx#:~:text=KibanaThemeProvider), [index_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx#:~:text=KibanaThemeProvider), [index_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx#:~:text=KibanaThemeProvider), [index_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx#:~:text=KibanaThemeProvider), [data_comparison_app_state.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/data_comparison/data_comparison_app_state.tsx#:~:text=KibanaThemeProvider)+ 2 more | - | | | [index_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx#:~:text=savedObjects) | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/common/types/index.ts#:~:text=SimpleSavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/common/types/index.ts#:~:text=SimpleSavedObject) | - | @@ -897,8 +877,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion) | - | -| | [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion)+ 14 more | - | +| | [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [install.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.test.ts#:~:text=migrationVersion) | - | +| | [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [get.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts#:~:text=migrationVersion), [install.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.test.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion), [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion)+ 22 more | - | | | [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title) | - | | | [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title) | - | | | [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title) | - | @@ -909,7 +889,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode) | 8.8.0 | | | [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/common/services/agent_policy_config.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode), [agent_policy_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/agent_policy_watch.test.ts#:~:text=mode) | 8.8.0 | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/integrations/index.tsx#:~:text=appBasePath) | 8.8.0 | -| | [install.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts#:~:text=migrationVersion) | - | @@ -1098,7 +1077,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [find_object_by_title.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_objects_utils/find_object_by_title.test.ts#:~:text=SimpleSavedObject), [find_object_by_title.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_objects_utils/find_object_by_title.test.ts#:~:text=SimpleSavedObject) | - | | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/types.ts#:~:text=ResolvedSimpleSavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/types.ts#:~:text=ResolvedSimpleSavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/types.ts#:~:text=ResolvedSimpleSavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/types.ts#:~:text=ResolvedSimpleSavedObject) | - | | | [find_object_by_title.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_objects_utils/find_object_by_title.test.ts#:~:text=simpleSavedObjectMock), [find_object_by_title.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_objects_utils/find_object_by_title.test.ts#:~:text=simpleSavedObjectMock) | - | -| | [saved_object_store.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_object_store.ts#:~:text=SavedObjectReference), [saved_object_store.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_object_store.ts#:~:text=SavedObjectReference), [saved_object_store.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_object_store.ts#:~:text=SavedObjectReference), [selectors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/state_management/selectors.ts#:~:text=SavedObjectReference), [selectors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/state_management/selectors.ts#:~:text=SavedObjectReference), [selectors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/state_management/selectors.ts#:~:text=SavedObjectReference), [state_helpers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts#:~:text=SavedObjectReference), [state_helpers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts#:~:text=SavedObjectReference), [state_helpers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts#:~:text=SavedObjectReference), [state_helpers.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts#:~:text=SavedObjectReference)+ 48 more | - | +| | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/common/embeddable_factory/index.ts#:~:text=SavedObjectReference), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/common/embeddable_factory/index.ts#:~:text=SavedObjectReference), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/common/embeddable_factory/index.ts#:~:text=SavedObjectReference), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/common/embeddable_factory/index.ts#:~:text=SavedObjectReference), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/common/embeddable_factory/index.ts#:~:text=SavedObjectReference), [saved_object_store.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_object_store.ts#:~:text=SavedObjectReference), [saved_object_store.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_object_store.ts#:~:text=SavedObjectReference), [saved_object_store.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/persistence/saved_object_store.ts#:~:text=SavedObjectReference), [selectors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/state_management/selectors.ts#:~:text=SavedObjectReference), [selectors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/state_management/selectors.ts#:~:text=SavedObjectReference)+ 48 more | - | | | [saved_objects.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/server/saved_objects.ts#:~:text=convertToMultiNamespaceTypeVersion) | - | @@ -1200,10 +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)+ 40 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)+ 40 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)+ 15 more | - | -| | [clone_action_name.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx#:~:text=toMountPoint), [clone_action_name.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx#:~:text=toMountPoint), [force_stop_dialog.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/model_management/force_stop_dialog.tsx#:~:text=toMountPoint), [force_stop_dialog.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/model_management/force_stop_dialog.tsx#:~:text=toMountPoint), [deployment_setup.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/model_management/deployment_setup.tsx#:~:text=toMountPoint), [deployment_setup.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/model_management/deployment_setup.tsx#:~:text=toMountPoint), [header_menu_portal.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/components/header_menu_portal/header_menu_portal.tsx#:~:text=toMountPoint), [header_menu_portal.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/components/header_menu_portal/header_menu_portal.tsx#:~:text=toMountPoint), [resolve_job_selection.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx#:~:text=toMountPoint), [resolve_job_selection.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx#:~:text=toMountPoint)+ 10 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 | @@ -1254,8 +1232,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=RedirectAppLinks), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=RedirectAppLinks), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=RedirectAppLinks) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=KibanaThemeProvider), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=KibanaThemeProvider), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=KibanaThemeProvider) | - | | | [render_cell_value.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/alerts_table/render_cell_value.tsx#:~:text=DeprecatedCellValueElementProps), [render_cell_value.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/alerts_table/render_cell_value.tsx#:~:text=DeprecatedCellValueElementProps) | - | -| | [use_fetch_slo_definitions.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_definitions.ts#:~:text=savedObjects) | - | -| | [use_fetch_slo_definitions.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_definitions.ts#:~:text=find) | - | @@ -1410,9 +1386,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [open_modal.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/components/edition_modal/open_modal.tsx#:~:text=toMountPoint), [open_modal.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/components/edition_modal/open_modal.tsx#:~:text=toMountPoint), [open_modal.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/components/edition_modal/open_modal.tsx#:~:text=toMountPoint), [open_assign_flyout.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/components/assign_flyout/open_assign_flyout.tsx#:~:text=toMountPoint), [open_assign_flyout.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/components/assign_flyout/open_assign_flyout.tsx#:~:text=toMountPoint) | - | | | [mount_section.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/management/mount_section.tsx#:~:text=KibanaThemeProvider), [mount_section.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/management/mount_section.tsx#:~:text=KibanaThemeProvider), [mount_section.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/management/mount_section.tsx#:~:text=KibanaThemeProvider) | - | | | [request_handler_context.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/server/request_handler_context.ts#:~:text=authz) | - | -| | [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObject), [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObject), [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObject), [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)+ 3 more | - | -| | [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObjectReference), [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~: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), [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)+ 11 more | - | -| | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/server/plugin.ts#:~:text=getAllIndices) | - | +| | [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 | - | | | [tag.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/saved_objects_tagging/server/saved_objects/tag.ts#:~:text=convertToMultiNamespaceTypeVersion) | - | @@ -1423,7 +1398,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | ---------------|-----------|-----------| | | [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/types.ts#:~:text=SavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/types.ts#:~:text=SavedObject), [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObject), [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObject) | 8.8.0 | | | [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObject), [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObject), [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObject) | - | -| | [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [inject_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/inject_tag_references.test.ts#:~:text=SavedObjectReference), [inject_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/inject_tag_references.test.ts#:~:text=SavedObjectReference), [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObjectReference), [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObjectReference)+ 2 more | - | +| | [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObjectReference), [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObjectReference), [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObjectReference), [api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/api.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference), [extract_tag_references.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts#:~:text=SavedObjectReference)+ 2 more | - | @@ -1484,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)+ 26 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)+ 26 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)+ 8 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 | @@ -1500,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), [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)+ 35 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)+ 33 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), [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)+ 17 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), [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)+ 15 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) | - | @@ -1530,14 +1505,6 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ -## serverlessSearch - -| Deprecated API | Reference location(s) | Remove By | -| ---------------|-----------|-----------| -| | [elasticsearch.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/serverless_search/public/application/elasticsearch.tsx#:~:text=KibanaThemeProvider), [elasticsearch.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/serverless_search/public/application/elasticsearch.tsx#:~:text=KibanaThemeProvider), [elasticsearch.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/serverless_search/public/application/elasticsearch.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), [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 | @@ -1637,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)+ 21 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) | - | @@ -1830,7 +1796,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [services.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/services.ts#:~:text=SavedObjectsStart), [services.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/services.ts#:~:text=SavedObjectsStart) | - | | | [saved_visualization_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts#:~:text=SavedObjectAttribute), [saved_visualization_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts#:~:text=SavedObjectAttribute) | - | | | [saved_visualize_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualize_utils.ts#:~:text=SavedObjectAttributes), [saved_visualize_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualize_utils.ts#:~:text=SavedObjectAttributes), [visualize_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx#:~:text=SavedObjectAttributes), [visualize_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx#:~:text=SavedObjectAttributes), [visualize_embeddable_factory.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx#:~:text=SavedObjectAttributes), [visualize_embeddable_factory.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx#:~:text=SavedObjectAttributes) | - | -| | [saved_visualization_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts#:~:text=SavedObjectReference), [saved_visualization_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts#:~:text=SavedObjectReference), [saved_visualization_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts#:~:text=SavedObjectReference), [saved_visualize_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualize_utils.ts#:~:text=SavedObjectReference), [saved_visualize_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualize_utils.ts#:~:text=SavedObjectReference), [saved_visualize_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualize_utils.ts#:~:text=SavedObjectReference), [saved_visualize_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualize_utils.ts#:~:text=SavedObjectReference), [saved_visualize_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualize_utils.ts#:~:text=SavedObjectReference), [saved_visualize_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualize_utils.ts#:~:text=SavedObjectReference), [visualize_embeddable_factory.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx#:~:text=SavedObjectReference)+ 10 more | - | +| | [controls_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts#:~:text=SavedObjectReference), [controls_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts#:~:text=SavedObjectReference), [controls_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts#:~:text=SavedObjectReference), [timeseries_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts#:~:text=SavedObjectReference), [timeseries_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts#:~:text=SavedObjectReference), [timeseries_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts#:~:text=SavedObjectReference), [saved_visualization_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts#:~:text=SavedObjectReference), [saved_visualization_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts#:~:text=SavedObjectReference), [saved_visualization_references.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts#:~:text=SavedObjectReference), [saved_visualize_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/utils/saved_visualize_utils.ts#:~:text=SavedObjectReference)+ 10 more | - | | | [visualization.ts](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/server/saved_objects/visualization.ts#:~:text=convertToMultiNamespaceTypeVersion) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 3cbc2fcddf409..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 978512db42e56..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-22 +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 8084995cc93ad..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-22 +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 6e366078040fd..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-22 +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 19f103eb80e2d..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-22 +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.devdocs.json b/api_docs/embeddable.devdocs.json index 91ca6c26e505e..59893ec0f6f38 100644 --- a/api_docs/embeddable.devdocs.json +++ b/api_docs/embeddable.devdocs.json @@ -1546,7 +1546,7 @@ "section": "def-common.PanelState", "text": "PanelState" }, - "<{ id: string; }>) => Promise) => Promise" + "<{ id: string; version?: string | undefined; }>" ], "path": "src/plugins/embeddable/public/lib/containers/container.ts", "deprecated": false, @@ -2169,7 +2169,7 @@ "label": "getDisplayName", "description": [], "signature": [ - "({ embeddable }: ActionContext) => any" + "({ embeddable }: ActionContext) => string" ], "path": "src/plugins/embeddable/public/embeddable_panel/panel_actions/edit_panel_action/edit_panel_action.ts", "deprecated": false, @@ -4262,7 +4262,7 @@ "label": "getDisplayName", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "src/plugins/embeddable/public/embeddable_panel/panel_actions/inspect_panel_action/inspect_panel_action.ts", "deprecated": false, @@ -4496,7 +4496,7 @@ "label": "getDisplayName", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "src/plugins/embeddable/public/embeddable_panel/panel_actions/remove_panel_action/remove_panel_action.ts", "deprecated": false, @@ -5874,6 +5874,133 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "embeddable", + "id": "def-public.runEmbeddableFactoryMigrations", + "type": "Function", + "tags": [], + "label": "runEmbeddableFactoryMigrations", + "description": [ + "\nA helper function that migrates an Embeddable Input to its latest version. Note that this function\nonly runs the embeddable factory's migrations." + ], + "signature": [ + "(initialInput: { version?: string | undefined; }, factory: { migrations?: ", + { + "pluginId": "kibanaUtils", + "scope": "common", + "docId": "kibKibanaUtilsPluginApi", + "section": "def-common.MigrateFunctionsObject", + "text": "MigrateFunctionsObject" + }, + " | ", + { + "pluginId": "kibanaUtils", + "scope": "common", + "docId": "kibKibanaUtilsPluginApi", + "section": "def-common.GetMigrationFunctionObjectFn", + "text": "GetMigrationFunctionObjectFn" + }, + " | undefined; latestVersion?: string | undefined; }) => { input: ToType; migrationRun: boolean; }" + ], + "path": "src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "embeddable", + "id": "def-public.runEmbeddableFactoryMigrations.$1", + "type": "Object", + "tags": [], + "label": "initialInput", + "description": [], + "path": "src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "embeddable", + "id": "def-public.runEmbeddableFactoryMigrations.$1.version", + "type": "string", + "tags": [], + "label": "version", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "embeddable", + "id": "def-public.runEmbeddableFactoryMigrations.$2", + "type": "Object", + "tags": [], + "label": "factory", + "description": [], + "path": "src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "embeddable", + "id": "def-public.runEmbeddableFactoryMigrations.$2.migrations", + "type": "CompoundType", + "tags": [], + "label": "migrations", + "description": [], + "signature": [ + { + "pluginId": "kibanaUtils", + "scope": "common", + "docId": "kibKibanaUtilsPluginApi", + "section": "def-common.MigrateFunctionsObject", + "text": "MigrateFunctionsObject" + }, + " | ", + { + "pluginId": "kibanaUtils", + "scope": "common", + "docId": "kibKibanaUtilsPluginApi", + "section": "def-common.GetMigrationFunctionObjectFn", + "text": "GetMigrationFunctionObjectFn" + }, + " | undefined" + ], + "path": "src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "embeddable", + "id": "def-public.runEmbeddableFactoryMigrations.$2.latestVersion", + "type": "string", + "tags": [], + "label": "latestVersion", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "embeddable", "id": "def-public.shouldFetch$", @@ -6562,6 +6689,22 @@ "deprecated": false, "trackAdoption": false, "children": [ + { + "parentPluginId": "embeddable", + "id": "def-public.EmbeddableFactory.latestVersion", + "type": "string", + "tags": [], + "label": "latestVersion", + "description": [ + "\nThe version of this Embeddable factory. This will be used in the client side migration system\nto ensure that input from any source is compatible with the latest version of this embeddable.\nIf the latest version is not defined, all clientside migrations will be skipped. If migrations\nare added to this factory but a latestVersion is not set, an error will be thrown on server start" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "embeddable", "id": "def-public.EmbeddableFactory.type", @@ -6916,7 +7059,7 @@ "tags": [], "label": "create", "description": [ - "\nResolves to undefined if a new Embeddable cannot be directly created and the user will instead be redirected\nelsewhere.\n\nThis will likely change in future iterations when we improve in place editing capabilities." + "\nCreates an Embeddable instance, running the inital input through all registered migrations. Resolves to undefined if a new Embeddable\ncannot be directly created and the user will instead be redirected elsewhere." ], "signature": [ "(initialInput: TEmbeddableInput, parent?: ", @@ -9293,20 +9436,6 @@ "path": "src/plugins/embeddable/common/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "embeddable", - "id": "def-public.PanelState.version", - "type": "string", - "tags": [], - "label": "version", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/embeddable/common/types.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -9845,7 +9974,7 @@ "section": "def-public.EmbeddableFactory", "text": "EmbeddableFactory" }, - ", \"create\" | \"type\" | \"isEditable\" | \"getDisplayName\"> & Partial, \"create\" | \"type\" | \"latestVersion\" | \"isEditable\" | \"getDisplayName\"> & Partial | undefined; readonly ssl: Readonly<{ certificateAuthorities?: string | string[] | undefined; } & { verificationMode: \"none\" | \"full\" | \"certificate\"; }>; readonly enabled: boolean; readonly accessCheckTimeout: number; readonly accessCheckTimeoutWarning: number; readonly canDeployEntSearch: boolean; readonly hasConnectors: boolean; readonly hasDefaultIngestPipeline: boolean; readonly hasDocumentLevelSecurityEnabled: boolean; readonly hasIncrementalSyncEnabled: boolean; readonly hasNativeConnectors: boolean; readonly hasWebCrawler: boolean; readonly isCloud: boolean; }" + "{ readonly host?: string | undefined; readonly customHeaders?: Readonly<{} & {}> | undefined; readonly ssl: Readonly<{ certificateAuthorities?: string | string[] | undefined; } & { verificationMode: \"none\" | \"full\" | \"certificate\"; }>; readonly enabled: boolean; readonly ui: Readonly<{} & { enabled: boolean; }>; readonly accessCheckTimeout: number; readonly accessCheckTimeoutWarning: number; readonly canDeployEntSearch: boolean; readonly hasConnectors: boolean; readonly hasDefaultIngestPipeline: boolean; readonly hasDocumentLevelSecurityEnabled: boolean; readonly hasIncrementalSyncEnabled: boolean; readonly hasNativeConnectors: boolean; readonly hasWebCrawler: boolean; readonly isCloud: boolean; }" ], "path": "x-pack/plugins/enterprise_search/server/index.ts", "deprecated": false, @@ -280,14 +280,43 @@ "section": "def-common.Type", "text": "Type" }, - "<\"none\" | \"full\" | \"certificate\">; }>; }>" + "<\"none\" | \"full\" | \"certificate\">; }>; ui: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ enabled: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; }>; }>" ], "path": "x-pack/plugins/enterprise_search/server/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false } - ] + ], + "start": { + "parentPluginId": "enterpriseSearch", + "id": "def-server.EnterpriseSearchPluginStart", + "type": "Type", + "tags": [], + "label": "EnterpriseSearchPluginStart", + "description": [], + "path": "x-pack/plugins/enterprise_search/server/index.ts", + "deprecated": false, + "trackAdoption": false, + "lifecycle": "start", + "initialIsOpen": true + } }, "common": { "classes": [], diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 2b9fb987dc1a9..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.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 | |-------------------|-----------|------------------------|-----------------| -| 10 | 0 | 10 | 0 | +| 11 | 0 | 11 | 0 | ## Client @@ -30,6 +30,9 @@ Contact [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/te ## Server +### Start + + ### Objects diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 5beca4d64f553..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-22 +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.devdocs.json b/api_docs/event_annotation.devdocs.json index a8456010389bb..e11e847c4ed5f 100644 --- a/api_docs/event_annotation.devdocs.json +++ b/api_docs/event_annotation.devdocs.json @@ -382,7 +382,7 @@ "section": "def-common.EventAnnotationGroupConfig", "text": "EventAnnotationGroupConfig" }, - ", \"annotations\" | \"ignoreGlobalFilters\" | \"indexPatternId\">[]; }) => ", + ", \"ignoreGlobalFilters\" | \"annotations\" | \"indexPatternId\">[]; }) => ", { "pluginId": "expressions", "scope": "common", @@ -434,7 +434,7 @@ "section": "def-common.EventAnnotationGroupConfig", "text": "EventAnnotationGroupConfig" }, - ", \"annotations\" | \"ignoreGlobalFilters\" | \"indexPatternId\">[]" + ", \"ignoreGlobalFilters\" | \"annotations\" | \"indexPatternId\">[]" ], "path": "packages/kbn-event-annotation-components/types.ts", "deprecated": false, @@ -1473,13 +1473,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -1551,13 +1548,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.args.id.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -1592,13 +1586,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.args.time.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -1633,13 +1624,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.args.label.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -1674,13 +1662,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.args.color.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -1729,13 +1714,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.args.lineStyle.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -1770,13 +1752,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.args.lineWidth.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -1811,13 +1790,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.args.icon.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -1880,13 +1856,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.args.textVisibility.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -1921,13 +1894,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualPointEventAnnotation.args.isHidden.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2080,13 +2050,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualRangeEventAnnotation.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2158,13 +2125,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualRangeEventAnnotation.args.id.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2199,13 +2163,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualRangeEventAnnotation.args.time.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2240,13 +2201,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualRangeEventAnnotation.args.endTime.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2347,13 +2305,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualRangeEventAnnotation.args.label.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2388,13 +2343,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualRangeEventAnnotation.args.color.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2429,13 +2381,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.manualRangeEventAnnotation.args.isHidden.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2556,13 +2505,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2634,13 +2580,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.id.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2675,13 +2618,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.filter.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2730,13 +2670,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.extraFields.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2771,13 +2708,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.timeField.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2812,13 +2746,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.label.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2853,13 +2784,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.color.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2908,13 +2836,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.lineStyle.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2949,13 +2874,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.lineWidth.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -2990,13 +2912,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.icon.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -3059,13 +2978,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.textVisibility.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -3100,13 +3016,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.textField.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false @@ -3141,13 +3054,10 @@ { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.isHidden.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index f0945f0e182ad..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.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 | |-------------------|-----------|------------------------|-----------------| -| 195 | 30 | 195 | 5 | +| 195 | 0 | 195 | 5 | ## Client diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index edb404868f80e..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-22 +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 a42ef1092c2d3..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-22 +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 9edeb48602e83..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.devdocs.json b/api_docs/expression_gauge.devdocs.json index eb53b79bbe044..6c131768104a0 100644 --- a/api_docs/expression_gauge.devdocs.json +++ b/api_docs/expression_gauge.devdocs.json @@ -1231,7 +1231,7 @@ "section": "def-common.MakeOverridesSerializable", "text": "MakeOverridesSerializable" }, - "; tooltipValueFormatter?: \"ignore\" | undefined; }>> & Partial; tooltipValueFormatter?: \"ignore\" | undefined; }>> & Partial { name: \"metric\"; aliases: never[]; type: \"render\"; inputTypes: (\"string\" | \"number\" | \"null\")[]; help: any; args: { label: { types: \"string\"[]; aliases: string[]; help: any; default: string; }; labelFont: { types: \"style\"[]; help: any; default: string; }; metricFont: { types: \"style\"[]; help: any; default: string; }; metricFormat: { types: \"string\"[]; aliases: string[]; help: any; }; }; fn: (input: ", + "() => { name: \"metric\"; aliases: never[]; type: \"render\"; inputTypes: (\"string\" | \"number\" | \"null\")[]; help: string; args: { label: { types: \"string\"[]; aliases: string[]; help: string; default: string; }; labelFont: { types: \"style\"[]; help: string; default: string; }; metricFont: { types: \"style\"[]; help: string; default: string; }; metricFormat: { types: \"string\"[]; aliases: string[]; help: string; }; }; fn: (input: ", { "pluginId": "expressionMetric", "scope": "common", diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 7f9766f8d9879..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-22 +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.devdocs.json b/api_docs/expression_metric_vis.devdocs.json index dfd0f3a000d80..aa7d4960d1447 100644 --- a/api_docs/expression_metric_vis.devdocs.json +++ b/api_docs/expression_metric_vis.devdocs.json @@ -868,7 +868,7 @@ "label": "overrides", "description": [], "signature": [ - "(Partial { name: \"repeatImage\"; aliases: never[]; type: \"render\"; inputTypes: \"number\"[]; help: any; args: { emptyImage: { types: (\"string\" | \"null\")[]; help: any; default: null; }; image: { types: (\"string\" | \"null\")[]; help: any; default: null; }; max: { types: (\"number\" | \"null\")[]; help: any; default: number; }; size: { types: \"number\"[]; default: number; help: any; }; }; fn: (count: number, args: Arguments) => Promise<{ type: \"render\"; as: string; value: { image: string | null; emptyImage: string | null; size: number; max: number | null; count: number; }; }>; }" + "() => { name: \"repeatImage\"; aliases: never[]; type: \"render\"; inputTypes: \"number\"[]; help: string; args: { emptyImage: { types: (\"string\" | \"null\")[]; help: string; default: null; }; image: { types: (\"string\" | \"null\")[]; help: string; default: null; }; max: { types: (\"number\" | \"null\")[]; help: string; default: number; }; size: { types: \"number\"[]; default: number; help: string; }; }; fn: (count: number, args: Arguments) => Promise<{ type: \"render\"; as: string; value: { image: string | null; emptyImage: string | null; size: number; max: number | null; count: number; }; }>; }" ], "path": "src/plugins/expression_repeat_image/common/expression_functions/repeat_image_function.ts", "deprecated": false, diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 1bf0f3ed5990b..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-22 +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.devdocs.json b/api_docs/expression_reveal_image.devdocs.json index 1b1e64a2fd210..950dce68bd57a 100644 --- a/api_docs/expression_reveal_image.devdocs.json +++ b/api_docs/expression_reveal_image.devdocs.json @@ -180,7 +180,7 @@ "label": "revealImageFunction", "description": [], "signature": [ - "() => { name: \"revealImage\"; aliases: never[]; type: \"render\"; inputTypes: \"number\"[]; help: any; args: { image: { types: (\"string\" | \"null\")[]; help: any; default: null; }; emptyImage: { types: (\"string\" | \"null\")[]; help: any; default: null; }; origin: { types: \"string\"[]; help: any; default: string; options: ", + "() => { name: \"revealImage\"; aliases: never[]; type: \"render\"; inputTypes: \"number\"[]; help: string; args: { image: { types: (\"string\" | \"null\")[]; help: string; default: null; }; emptyImage: { types: (\"string\" | \"null\")[]; help: string; default: null; }; origin: { types: \"string\"[]; help: string; default: string; options: ", "Origin", "[]; }; }; fn: (percent: number, args: Arguments) => Promise<{ type: \"render\"; as: string; value: { image: string; emptyImage: string; origin: ", "Origin", diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index c2a874fa054fd..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-22 +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 63d16038a95ef..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-22 +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 7e31be6b1b19e..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-22 +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.devdocs.json b/api_docs/expression_x_y.devdocs.json index 748dacf2ef706..02acfe81488e7 100644 --- a/api_docs/expression_x_y.devdocs.json +++ b/api_docs/expression_x_y.devdocs.json @@ -1916,7 +1916,7 @@ }, "<", "YDomainRange", - " | undefined>; hide?: boolean | undefined; showOverlappingTicks?: boolean | undefined; showOverlappingLabels?: boolean | undefined; timeAxisLayerCount?: number | undefined; integersOnly?: boolean | undefined; tickFormat?: \"ignore\" | undefined; labelFormat?: \"ignore\" | undefined; showDuplicatedTicks?: boolean | undefined; }>> & Partial; hide?: boolean | undefined; showOverlappingTicks?: boolean | undefined; showOverlappingLabels?: boolean | undefined; timeAxisLayerCount?: number | undefined; integersOnly?: boolean | undefined; tickFormat?: \"ignore\" | undefined; labelFormat?: \"ignore\" | undefined; showDuplicatedTicks?: boolean | undefined; }>> & Partial" + " | undefined; warning?: string | undefined; }>" ], "path": "src/plugins/expressions/common/expression_functions/specs/map_column.ts", "deprecated": false, @@ -42012,13 +41967,10 @@ { "parentPluginId": "expressions", "id": "def-common.math.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/math.ts", "deprecated": false, "trackAdoption": false @@ -42076,13 +42028,10 @@ { "parentPluginId": "expressions", "id": "def-common.math.args.expression.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/math.ts", "deprecated": false, "trackAdoption": false @@ -42131,13 +42080,10 @@ { "parentPluginId": "expressions", "id": "def-common.math.args.onError.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/math.ts", "deprecated": false, "trackAdoption": false @@ -42280,13 +42226,10 @@ { "parentPluginId": "expressions", "id": "def-common.mathColumn.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/math_column.ts", "deprecated": false, "trackAdoption": false @@ -42344,13 +42287,10 @@ { "parentPluginId": "expressions", "id": "def-common.mathColumn.args.id.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/math_column.ts", "deprecated": false, "trackAdoption": false @@ -42413,13 +42353,10 @@ { "parentPluginId": "expressions", "id": "def-common.mathColumn.args.name.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/math_column.ts", "deprecated": false, "trackAdoption": false @@ -42482,13 +42419,10 @@ { "parentPluginId": "expressions", "id": "def-common.mathColumn.args.castColumns.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/math_column.ts", "deprecated": false, "trackAdoption": false @@ -42537,13 +42471,10 @@ { "parentPluginId": "expressions", "id": "def-common.mathColumn.args.copyMetaFrom.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/math_column.ts", "deprecated": false, "trackAdoption": false @@ -42786,13 +42717,10 @@ { "parentPluginId": "expressions", "id": "def-common.movingAverage.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/moving_average.ts", "deprecated": false, "trackAdoption": false @@ -42822,13 +42750,10 @@ { "parentPluginId": "expressions", "id": "def-common.movingAverage.args.by.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/moving_average.ts", "deprecated": false, "trackAdoption": false @@ -42891,13 +42816,10 @@ { "parentPluginId": "expressions", "id": "def-common.movingAverage.args.inputColumnId.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/moving_average.ts", "deprecated": false, "trackAdoption": false @@ -42946,13 +42868,10 @@ { "parentPluginId": "expressions", "id": "def-common.movingAverage.args.outputColumnId.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/moving_average.ts", "deprecated": false, "trackAdoption": false @@ -43001,13 +42920,10 @@ { "parentPluginId": "expressions", "id": "def-common.movingAverage.args.outputColumnName.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/moving_average.ts", "deprecated": false, "trackAdoption": false @@ -43056,13 +42972,10 @@ { "parentPluginId": "expressions", "id": "def-common.movingAverage.args.window.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/moving_average.ts", "deprecated": false, "trackAdoption": false @@ -43818,13 +43731,10 @@ { "parentPluginId": "expressions", "id": "def-common.overallMetric.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/overall_metric.ts", "deprecated": false, "trackAdoption": false @@ -43854,13 +43764,10 @@ { "parentPluginId": "expressions", "id": "def-common.overallMetric.args.by.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/overall_metric.ts", "deprecated": false, "trackAdoption": false @@ -43923,13 +43830,10 @@ { "parentPluginId": "expressions", "id": "def-common.overallMetric.args.metric.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/overall_metric.ts", "deprecated": false, "trackAdoption": false @@ -43978,13 +43882,10 @@ { "parentPluginId": "expressions", "id": "def-common.overallMetric.args.inputColumnId.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/overall_metric.ts", "deprecated": false, "trackAdoption": false @@ -44033,13 +43934,10 @@ { "parentPluginId": "expressions", "id": "def-common.overallMetric.args.outputColumnId.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/overall_metric.ts", "deprecated": false, "trackAdoption": false @@ -44088,13 +43986,10 @@ { "parentPluginId": "expressions", "id": "def-common.overallMetric.args.outputColumnName.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/overall_metric.ts", "deprecated": false, "trackAdoption": false @@ -45355,13 +45250,10 @@ { "parentPluginId": "expressions", "id": "def-common.theme.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/theme.ts", "deprecated": false, "trackAdoption": false @@ -45419,13 +45311,10 @@ { "parentPluginId": "expressions", "id": "def-common.theme.args.variable.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/theme.ts", "deprecated": false, "trackAdoption": false @@ -45474,13 +45363,10 @@ { "parentPluginId": "expressions", "id": "def-common.theme.args.default.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/theme.ts", "deprecated": false, "trackAdoption": false @@ -45915,13 +45801,10 @@ { "parentPluginId": "expressions", "id": "def-common.variable.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/var.ts", "deprecated": false, "trackAdoption": false @@ -45993,13 +45876,10 @@ { "parentPluginId": "expressions", "id": "def-common.variable.args.name.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/var.ts", "deprecated": false, "trackAdoption": false @@ -46148,13 +46028,10 @@ { "parentPluginId": "expressions", "id": "def-common.variableSet.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/var_set.ts", "deprecated": false, "trackAdoption": false @@ -46240,13 +46117,10 @@ { "parentPluginId": "expressions", "id": "def-common.variableSet.args.name.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/var_set.ts", "deprecated": false, "trackAdoption": false @@ -46295,13 +46169,10 @@ { "parentPluginId": "expressions", "id": "def-common.variableSet.args.value.help", - "type": "Any", + "type": "string", "tags": [], "label": "help", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/expressions/common/expression_functions/specs/var_set.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 38792f79d8586..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-22 +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 | 74 | 1746 | 5 | +| 2208 | 17 | 1749 | 5 | ## Client diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 840b3000475e4..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.devdocs.json b/api_docs/field_formats.devdocs.json index 066b2d29c4761..c0d04c8516b70 100644 --- a/api_docs/field_formats.devdocs.json +++ b/api_docs/field_formats.devdocs.json @@ -53,13 +53,10 @@ { "parentPluginId": "fieldFormats", "id": "def-public.DateFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/public/lib/converters/date.ts", "deprecated": false, "trackAdoption": false @@ -196,13 +193,10 @@ { "parentPluginId": "fieldFormats", "id": "def-public.DateNanosFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/date_nanos_shared.ts", "deprecated": false, "trackAdoption": false @@ -454,13 +448,10 @@ { "parentPluginId": "fieldFormats", "id": "def-server.DateFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/server/lib/converters/date_server.ts", "deprecated": false, "trackAdoption": false @@ -939,13 +930,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.BoolFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/boolean.ts", "deprecated": false, "trackAdoption": false @@ -1081,13 +1069,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.BytesFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/bytes.ts", "deprecated": false, "trackAdoption": false @@ -1115,13 +1100,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.BytesFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/bytes.ts", "deprecated": false, "trackAdoption": false @@ -1191,13 +1173,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.ColorFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/color.tsx", "deprecated": false, "trackAdoption": false @@ -1387,13 +1366,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.DurationFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/duration.ts", "deprecated": false, "trackAdoption": false @@ -1426,7 +1402,7 @@ "label": "inputFormats", "description": [], "signature": [ - "{ text: any; kind: string; }[]" + "{ text: string; kind: string; }[]" ], "path": "src/plugins/field_formats/common/converters/duration.ts", "deprecated": false, @@ -1440,7 +1416,7 @@ "label": "outputFormats", "description": [], "signature": [ - "({ text: any; method: string; shortText?: undefined; } | { text: any; shortText: any; method: string; })[]" + "({ text: string; method: string; shortText?: undefined; } | { text: string; shortText: string; method: string; })[]" ], "path": "src/plugins/field_formats/common/converters/duration.ts", "deprecated": false, @@ -3613,13 +3589,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.GeoPointFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/geo_point.ts", "deprecated": false, "trackAdoption": false @@ -3653,7 +3626,7 @@ "label": "transformOptions", "description": [], "signature": [ - "{ kind: string; text: any; }[]" + "{ kind: string; text: string; }[]" ], "path": "src/plugins/field_formats/common/converters/geo_point.ts", "deprecated": false, @@ -3811,13 +3784,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.HistogramFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/histogram.ts", "deprecated": false, "trackAdoption": false @@ -3845,13 +3815,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.HistogramFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/histogram.ts", "deprecated": false, "trackAdoption": false @@ -3999,13 +3966,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.IpFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/ip.ts", "deprecated": false, "trackAdoption": false @@ -4110,13 +4074,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.NumberFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/number.ts", "deprecated": false, "trackAdoption": false @@ -4144,13 +4105,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.NumberFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/number.ts", "deprecated": false, "trackAdoption": false @@ -4214,13 +4172,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.PercentFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/percent.ts", "deprecated": false, "trackAdoption": false @@ -4248,13 +4203,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.PercentFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/percent.ts", "deprecated": false, "trackAdoption": false @@ -4380,13 +4332,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.RelativeDateFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/relative_date.ts", "deprecated": false, "trackAdoption": false @@ -4497,13 +4446,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.StaticLookupFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/static_lookup.ts", "deprecated": false, "trackAdoption": false @@ -4631,13 +4577,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.StringFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/string.ts", "deprecated": false, "trackAdoption": false @@ -4671,7 +4614,7 @@ "label": "transformOptions", "description": [], "signature": [ - "({ kind: boolean; text: any; } | { kind: string; text: any; })[]" + "({ kind: boolean; text: string; } | { kind: string; text: string; })[]" ], "path": "src/plugins/field_formats/common/converters/string.ts", "deprecated": false, @@ -4709,7 +4652,7 @@ "section": "def-common.TextContextTypeOptions", "text": "TextContextTypeOptions" }, - " | undefined) => any" + " | undefined) => string" ], "path": "src/plugins/field_formats/common/converters/string.ts", "deprecated": false, @@ -4871,13 +4814,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.TruncateFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/truncate.ts", "deprecated": false, "trackAdoption": false @@ -4988,13 +4928,10 @@ { "parentPluginId": "fieldFormats", "id": "def-common.UrlFormat.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/field_formats/common/converters/url.ts", "deprecated": false, "trackAdoption": false @@ -5028,7 +4965,7 @@ "label": "urlTypes", "description": [], "signature": [ - "{ kind: string; text: any; }[]" + "{ kind: string; text: string; }[]" ], "path": "src/plugins/field_formats/common/converters/url.ts", "deprecated": false, @@ -5542,7 +5479,7 @@ "label": "DURATION_INPUT_FORMATS", "description": [], "signature": [ - "{ text: any; kind: string; }[]" + "{ text: string; kind: string; }[]" ], "path": "src/plugins/field_formats/common/constants/duration_formats.ts", "deprecated": false, @@ -5557,7 +5494,7 @@ "label": "DURATION_OUTPUT_FORMATS", "description": [], "signature": [ - "({ text: any; method: string; shortText?: undefined; } | { text: any; shortText: any; method: string; })[]" + "({ text: string; method: string; shortText?: undefined; } | { text: string; shortText: string; method: string; })[]" ], "path": "src/plugins/field_formats/common/constants/duration_formats.ts", "deprecated": false, @@ -6652,7 +6589,7 @@ "label": "DEFAULT_DURATION_INPUT_FORMAT", "description": [], "signature": [ - "{ text: any; kind: string; }" + "{ text: string; kind: string; }" ], "path": "src/plugins/field_formats/common/constants/duration_formats.ts", "deprecated": false, @@ -6667,7 +6604,7 @@ "label": "DEFAULT_DURATION_OUTPUT_FORMAT", "description": [], "signature": [ - "{ text: any; method: string; }" + "{ text: string; method: string; }" ], "path": "src/plugins/field_formats/common/constants/duration_formats.ts", "deprecated": false, diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 1250b62d6986e..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.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 | |-------------------|-----------|------------------------|-----------------| -| 292 | 26 | 253 | 3 | +| 292 | 5 | 253 | 3 | ## Client diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index aee7c00433d2e..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-22 +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 21e658389deb6..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.devdocs.json b/api_docs/files_management.devdocs.json index cf433bf45ec7e..5568b8b1261fa 100644 --- a/api_docs/files_management.devdocs.json +++ b/api_docs/files_management.devdocs.json @@ -40,13 +40,10 @@ { "parentPluginId": "filesManagement", "id": "def-common.PLUGIN_NAME", - "type": "Any", + "type": "string", "tags": [], "label": "PLUGIN_NAME", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/files_management/common/index.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 0cc7cc60a7097..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.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 | |-------------------|-----------|------------------------|-----------------| -| 2 | 1 | 2 | 0 | +| 2 | 0 | 2 | 0 | ## Common diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index f2d95d5d0909e..81bd886607d5f 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -656,6 +656,26 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "fleet", + "id": "def-public.FleetStartServices.dashboard", + "type": "Object", + "tags": [], + "label": "dashboard", + "description": [], + "signature": [ + { + "pluginId": "dashboard", + "scope": "public", + "docId": "kibDashboardPluginApi", + "section": "def-public.DashboardStart", + "text": "DashboardStart" + } + ], + "path": "x-pack/plugins/fleet/public/plugin.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "fleet", "id": "def-public.FleetStartServices.cloud", @@ -23920,7 +23940,7 @@ "section": "def-common.RegistryPackage", "text": "RegistryPackage" }, - ", \"internal\" | \"assets\" | \"elasticsearch\" | \"readme\" | \"data_streams\">" + ", \"assets\" | \"internal\" | \"elasticsearch\" | \"readme\" | \"data_streams\">" ], "path": "x-pack/plugins/fleet/common/types/models/epm.ts", "deprecated": false, diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 5d57b6678f33a..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1188 | 3 | 1072 | 41 | +| 1189 | 3 | 1073 | 41 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index e6522d611ab2e..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-22 +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 fc76fb9e2d959..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.devdocs.json b/api_docs/home.devdocs.json index 63a5d51330144..e39bab658985d 100644 --- a/api_docs/home.devdocs.json +++ b/api_docs/home.devdocs.json @@ -107,11 +107,21 @@ "parentPluginId": "home", "id": "def-public.FeatureCatalogueRegistry.get", "type": "Function", - "tags": [], + "tags": [ + "deprecated" + ], "label": "get", "description": [], "signature": [ - "() => ", + "(features?: Map) => ", { "pluginId": "home", "scope": "public", @@ -122,6 +132,57 @@ "[]" ], "path": "src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts", + "deprecated": true, + "trackAdoption": false, + "references": [], + "children": [ + { + "parentPluginId": "home", + "id": "def-public.FeatureCatalogueRegistry.get.$1", + "type": "Object", + "tags": [], + "label": "features", + "description": [], + "signature": [ + "Map" + ], + "path": "src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "home", + "id": "def-public.FeatureCatalogueRegistry.getFeatures$", + "type": "Function", + "tags": [], + "label": "getFeatures$", + "description": [], + "signature": [ + "() => ", + "Observable", + "<", + { + "pluginId": "home", + "scope": "public", + "docId": "kibHomePluginApi", + "section": "def-public.FeatureCatalogueEntry", + "text": "FeatureCatalogueEntry" + }, + "[]>" + ], + "path": "src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts", "deprecated": false, "trackAdoption": false, "children": [], @@ -201,7 +262,7 @@ "\nConvert instruction variant id into display text.\n" ], "signature": [ - "(id: \"ESC\" | \"OSX\" | \"DEB\" | \"RPM\" | \"DOCKER\" | \"WINDOWS\" | \"NODE\" | \"DJANGO\" | \"FLASK\" | \"RAILS\" | \"RACK\" | \"JS\" | \"GO\" | \"JAVA\" | \"DOTNET\" | \"LINUX\" | \"PHP\" | \"FLEET\" | \"OPEN_TELEMETRY\" | \"OTHER_LINUX\") => any" + "(id: \"ESC\" | \"OSX\" | \"DEB\" | \"RPM\" | \"DOCKER\" | \"WINDOWS\" | \"NODE\" | \"DJANGO\" | \"FLASK\" | \"RAILS\" | \"RACK\" | \"JS\" | \"GO\" | \"JAVA\" | \"DOTNET\" | \"LINUX\" | \"PHP\" | \"FLEET\" | \"OPEN_TELEMETRY\" | \"OTHER_LINUX\") => string" ], "path": "src/plugins/home/common/instruction_variant.ts", "deprecated": false, diff --git a/api_docs/home.mdx b/api_docs/home.mdx index f278f248c80a8..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.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 | |-------------------|-----------|------------------------|-----------------| -| 145 | 0 | 106 | 0 | +| 147 | 0 | 108 | 0 | ## Client diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index d878c3b1e0282..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-22 +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 7a322702eb41e..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-22 +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 9bfac0cb5d6df..6d3b01d5245cf 100644 --- a/api_docs/index_management.devdocs.json +++ b/api_docs/index_management.devdocs.json @@ -114,13 +114,24 @@ "children": [ { "parentPluginId": "indexManagement", - "id": "def-public.Index.health", + "id": "def-public.Index.name", "type": "string", "tags": [], - "label": "health", + "label": "name", + "description": [], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-public.Index.primary", + "type": "CompoundType", + "tags": [], + "label": "primary", "description": [], "signature": [ - "string | undefined" + "string | number | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -128,13 +139,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.status", - "type": "string", + "id": "def-public.Index.replica", + "type": "CompoundType", "tags": [], - "label": "status", + "label": "replica", "description": [], "signature": [ - "string | undefined" + "string | number | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -142,10 +153,10 @@ }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.name", - "type": "string", + "id": "def-public.Index.isFrozen", + "type": "boolean", "tags": [], - "label": "name", + "label": "isFrozen", "description": [], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -153,13 +164,24 @@ }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.uuid", - "type": "string", + "id": "def-public.Index.hidden", + "type": "boolean", "tags": [], - "label": "uuid", + "label": "hidden", + "description": [], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-public.Index.aliases", + "type": "CompoundType", + "tags": [], + "label": "aliases", "description": [], "signature": [ - "string | undefined" + "string | string[]" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -167,13 +189,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.primary", - "type": "CompoundType", + "id": "def-public.Index.data_stream", + "type": "string", "tags": [], - "label": "primary", + "label": "data_stream", "description": [], "signature": [ - "string | number | undefined" + "string | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -181,13 +203,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.replica", + "id": "def-public.Index.isRollupIndex", "type": "CompoundType", "tags": [], - "label": "replica", + "label": "isRollupIndex", "description": [], "signature": [ - "string | number | undefined" + "boolean | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -195,79 +217,99 @@ }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.documents", - "type": "number", + "id": "def-public.Index.ilm", + "type": "Object", "tags": [], - "label": "documents", + "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.documents_deleted", - "type": "number", + "id": "def-public.Index.isFollowerIndex", + "type": "CompoundType", "tags": [], - "label": "documents_deleted", + "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.size", - "type": "string", + "id": "def-public.Index.health", + "type": "CompoundType", "tags": [], - "label": "size", + "label": "health", "description": [], + "signature": [ + "HealthStatus", + " | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.primary_size", - "type": "string", + "id": "def-public.Index.status", + "type": "CompoundType", "tags": [], - "label": "primary_size", + "label": "status", "description": [], + "signature": [ + "IndicesStatsIndexMetadataState", + " | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.isFrozen", - "type": "boolean", + "id": "def-public.Index.uuid", + "type": "string", "tags": [], - "label": "isFrozen", + "label": "uuid", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.hidden", - "type": "boolean", + "id": "def-public.Index.documents", + "type": "number", "tags": [], - "label": "hidden", + "label": "documents", "description": [], + "signature": [ + "number | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.aliases", - "type": "CompoundType", + "id": "def-public.Index.size", + "type": "string", "tags": [], - "label": "aliases", + "label": "size", "description": [], "signature": [ - "string | string[]" + "string | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -275,10 +317,10 @@ }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.data_stream", + "id": "def-public.Index.primary_size", "type": "string", "tags": [], - "label": "data_stream", + "label": "primary_size", "description": [], "signature": [ "string | undefined" @@ -289,13 +331,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-public.Index.Unnamed", - "type": "IndexSignature", + "id": "def-public.Index.documents_deleted", + "type": "number", "tags": [], - "label": "[key: string]: any", + "label": "documents_deleted", "description": [], "signature": [ - "[key: string]: any" + "number | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -442,13 +484,24 @@ "children": [ { "parentPluginId": "indexManagement", - "id": "def-server.Index.health", + "id": "def-server.Index.name", "type": "string", "tags": [], - "label": "health", + "label": "name", + "description": [], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-server.Index.primary", + "type": "CompoundType", + "tags": [], + "label": "primary", "description": [], "signature": [ - "string | undefined" + "string | number | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -456,13 +509,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.status", - "type": "string", + "id": "def-server.Index.replica", + "type": "CompoundType", "tags": [], - "label": "status", + "label": "replica", "description": [], "signature": [ - "string | undefined" + "string | number | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -470,10 +523,10 @@ }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.name", - "type": "string", + "id": "def-server.Index.isFrozen", + "type": "boolean", "tags": [], - "label": "name", + "label": "isFrozen", "description": [], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -481,13 +534,24 @@ }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.uuid", - "type": "string", + "id": "def-server.Index.hidden", + "type": "boolean", "tags": [], - "label": "uuid", + "label": "hidden", + "description": [], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-server.Index.aliases", + "type": "CompoundType", + "tags": [], + "label": "aliases", "description": [], "signature": [ - "string | undefined" + "string | string[]" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -495,13 +559,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.primary", - "type": "CompoundType", + "id": "def-server.Index.data_stream", + "type": "string", "tags": [], - "label": "primary", + "label": "data_stream", "description": [], "signature": [ - "string | number | undefined" + "string | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -509,13 +573,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.replica", + "id": "def-server.Index.isRollupIndex", "type": "CompoundType", "tags": [], - "label": "replica", + "label": "isRollupIndex", "description": [], "signature": [ - "string | number | undefined" + "boolean | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -523,79 +587,99 @@ }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.documents", - "type": "number", + "id": "def-server.Index.ilm", + "type": "Object", "tags": [], - "label": "documents", + "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.documents_deleted", - "type": "number", + "id": "def-server.Index.isFollowerIndex", + "type": "CompoundType", "tags": [], - "label": "documents_deleted", + "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.size", - "type": "string", + "id": "def-server.Index.health", + "type": "CompoundType", "tags": [], - "label": "size", + "label": "health", "description": [], + "signature": [ + "HealthStatus", + " | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.primary_size", - "type": "string", + "id": "def-server.Index.status", + "type": "CompoundType", "tags": [], - "label": "primary_size", + "label": "status", "description": [], + "signature": [ + "IndicesStatsIndexMetadataState", + " | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.isFrozen", - "type": "boolean", + "id": "def-server.Index.uuid", + "type": "string", "tags": [], - "label": "isFrozen", + "label": "uuid", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.hidden", - "type": "boolean", + "id": "def-server.Index.documents", + "type": "number", "tags": [], - "label": "hidden", + "label": "documents", "description": [], + "signature": [ + "number | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.aliases", - "type": "CompoundType", + "id": "def-server.Index.size", + "type": "string", "tags": [], - "label": "aliases", + "label": "size", "description": [], "signature": [ - "string | string[]" + "string | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -603,10 +687,10 @@ }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.data_stream", + "id": "def-server.Index.primary_size", "type": "string", "tags": [], - "label": "data_stream", + "label": "primary_size", "description": [], "signature": [ "string | undefined" @@ -617,13 +701,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-server.Index.Unnamed", - "type": "IndexSignature", + "id": "def-server.Index.documents_deleted", + "type": "number", "tags": [], - "label": "[key: string]: any", + "label": "documents_deleted", "description": [], "signature": [ - "[key: string]: any" + "number | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -764,7 +848,7 @@ "label": "IndexManagementConfig", "description": [], "signature": [ - "{ readonly ui: Readonly<{} & { enabled: boolean; }>; readonly enableIndexActions: boolean; readonly enableLegacyTemplates: boolean; readonly dev: Readonly<{} & { enableIndexDetailsPage: boolean; }>; }" + "{ readonly ui: Readonly<{} & { enabled: boolean; }>; readonly enableIndexActions: boolean; readonly enableLegacyTemplates: boolean; readonly dev: Readonly<{} & { enableIndexDetailsPage: boolean; }>; readonly enableIndexStats: boolean; }" ], "path": "x-pack/plugins/index_management/server/config.ts", "deprecated": false, @@ -1641,13 +1725,24 @@ "children": [ { "parentPluginId": "indexManagement", - "id": "def-common.Index.health", + "id": "def-common.Index.name", "type": "string", "tags": [], - "label": "health", + "label": "name", + "description": [], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-common.Index.primary", + "type": "CompoundType", + "tags": [], + "label": "primary", "description": [], "signature": [ - "string | undefined" + "string | number | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -1655,13 +1750,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.status", - "type": "string", + "id": "def-common.Index.replica", + "type": "CompoundType", "tags": [], - "label": "status", + "label": "replica", "description": [], "signature": [ - "string | undefined" + "string | number | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -1669,10 +1764,10 @@ }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.name", - "type": "string", + "id": "def-common.Index.isFrozen", + "type": "boolean", "tags": [], - "label": "name", + "label": "isFrozen", "description": [], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -1680,13 +1775,24 @@ }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.uuid", - "type": "string", + "id": "def-common.Index.hidden", + "type": "boolean", "tags": [], - "label": "uuid", + "label": "hidden", + "description": [], + "path": "x-pack/plugins/index_management/common/types/indices.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-common.Index.aliases", + "type": "CompoundType", + "tags": [], + "label": "aliases", "description": [], "signature": [ - "string | undefined" + "string | string[]" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -1694,13 +1800,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.primary", - "type": "CompoundType", + "id": "def-common.Index.data_stream", + "type": "string", "tags": [], - "label": "primary", + "label": "data_stream", "description": [], "signature": [ - "string | number | undefined" + "string | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -1708,13 +1814,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.replica", + "id": "def-common.Index.isRollupIndex", "type": "CompoundType", "tags": [], - "label": "replica", + "label": "isRollupIndex", "description": [], "signature": [ - "string | number | undefined" + "boolean | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -1722,79 +1828,99 @@ }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.documents", - "type": "number", + "id": "def-common.Index.ilm", + "type": "Object", "tags": [], - "label": "documents", + "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.documents_deleted", - "type": "number", + "id": "def-common.Index.isFollowerIndex", + "type": "CompoundType", "tags": [], - "label": "documents_deleted", + "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.size", - "type": "string", + "id": "def-common.Index.health", + "type": "CompoundType", "tags": [], - "label": "size", + "label": "health", "description": [], + "signature": [ + "HealthStatus", + " | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.primary_size", - "type": "string", + "id": "def-common.Index.status", + "type": "CompoundType", "tags": [], - "label": "primary_size", + "label": "status", "description": [], + "signature": [ + "IndicesStatsIndexMetadataState", + " | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.isFrozen", - "type": "boolean", + "id": "def-common.Index.uuid", + "type": "string", "tags": [], - "label": "isFrozen", + "label": "uuid", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.hidden", - "type": "boolean", + "id": "def-common.Index.documents", + "type": "number", "tags": [], - "label": "hidden", + "label": "documents", "description": [], + "signature": [ + "number | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.aliases", - "type": "CompoundType", + "id": "def-common.Index.size", + "type": "string", "tags": [], - "label": "aliases", + "label": "size", "description": [], "signature": [ - "string | string[]" + "string | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, @@ -1802,10 +1928,10 @@ }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.data_stream", + "id": "def-common.Index.primary_size", "type": "string", "tags": [], - "label": "data_stream", + "label": "primary_size", "description": [], "signature": [ "string | undefined" @@ -1816,13 +1942,13 @@ }, { "parentPluginId": "indexManagement", - "id": "def-common.Index.Unnamed", - "type": "IndexSignature", + "id": "def-common.Index.documents_deleted", + "type": "number", "tags": [], - "label": "[key: string]: any", + "label": "documents_deleted", "description": [], "signature": [ - "[key: string]: any" + "number | undefined" ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false, diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index c8ce675099881..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 185 | 0 | 180 | 4 | +| 191 | 0 | 186 | 4 | ## Client diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index dc5c82c7aba8e..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-22 +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 a75b0fd3fa809..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-22 +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 40c3de6ef8c01..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-22 +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 c405cdbb4db68..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-22 +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 3a427c3d810e1..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-22 +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 7fd30f4e6bd1d..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-22 +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 2fe86f2d22b8b..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-22 +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 6737b11b51f03..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-22 +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 a9afa800b7e69..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-22 +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 85acfc92a413f..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-22 +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 729a79904b379..08169d4866da6 100644 --- a/api_docs/kbn_analytics_client.devdocs.json +++ b/api_docs/kbn_analytics_client.devdocs.json @@ -602,38 +602,6 @@ "deprecated": false, "trackAdoption": true, "references": [ - { - "plugin": "@kbn/ebt-tools", - "path": "packages/kbn-ebt-tools/src/performance_metric_events/helpers.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-root-browser-internal", - "path": "packages/core/root/core-root-browser-internal/src/core_system.ts" - }, { "plugin": "@kbn/core-status-server-internal", "path": "packages/core/status/core-status-server-internal/src/status_service.ts" @@ -662,6 +630,10 @@ "plugin": "@kbn/core-plugins-server-internal", "path": "packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts" }, + { + "plugin": "@kbn/ebt-tools", + "path": "packages/kbn-ebt-tools/src/performance_metric_events/helpers.ts" + }, { "plugin": "@kbn/core-analytics-server-internal", "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" @@ -690,6 +662,34 @@ "plugin": "@kbn/core-root-server-internal", "path": "packages/core/root/core-root-server-internal/src/server.ts" }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-root-browser-internal", + "path": "packages/core/root/core-root-browser-internal/src/core_system.ts" + }, { "plugin": "security", "path": "x-pack/plugins/security/server/analytics/analytics_service.ts" @@ -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" @@ -1256,46 +1256,6 @@ "deprecated": false, "trackAdoption": true, "references": [ - { - "plugin": "@kbn/core-application-browser-internal", - "path": "packages/core/application/core-application-browser-internal/src/register_analytics_context_provider.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-analytics-browser-internal", - "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" - }, - { - "plugin": "@kbn/core-execution-context-browser-internal", - "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.ts" - }, - { - "plugin": "@kbn/core-chrome-browser-internal", - "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.ts" - }, { "plugin": "@kbn/core-elasticsearch-server-internal", "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.ts" @@ -1348,6 +1308,46 @@ "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" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/track_viewport_size.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-analytics-browser-internal", + "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts" + }, + { + "plugin": "@kbn/core-execution-context-browser-internal", + "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.ts" + }, + { + "plugin": "@kbn/core-chrome-browser-internal", + "path": "packages/core/chrome/core-chrome-browser-internal/src/register_analytics_context_provider.ts" + }, { "plugin": "cloud", "path": "x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts" @@ -1358,11 +1358,11 @@ }, { "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 5d9ab96b22204..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-22 +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 b45b51a34f87f..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-22 +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 917f2488b8911..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-22 +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 e053f76a81c4b..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-22 +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 30d140b612a04..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-22 +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 335a0a6ea6b07..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-22 +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 96e67e175b3c1..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-22 +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 bceb838a745f7..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-22 +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 22217bd57e12b..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-22 +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 fae7d6590ecdf..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-22 +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 2427430fc187e..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-22 +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.devdocs.json b/api_docs/kbn_cases_components.devdocs.json index 45a0779eaea00..074fdc9435b06 100644 --- a/api_docs/kbn_cases_components.devdocs.json +++ b/api_docs/kbn_cases_components.devdocs.json @@ -27,7 +27,7 @@ "label": "getStatusConfiguration", "description": [], "signature": [ - "() => { open: { color: string; label: any; icon: \"folderOpen\"; }; \"in-progress\": { color: string; label: any; icon: \"folderExclamation\"; }; closed: { color: string; label: any; icon: \"folderCheck\"; }; }" + "() => { open: { color: string; label: string; icon: \"folderOpen\"; }; \"in-progress\": { color: string; label: string; icon: \"folderExclamation\"; }; closed: { color: string; label: string; icon: \"folderCheck\"; }; }" ], "path": "packages/kbn-cases-components/src/status/config.ts", "deprecated": false, diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index c01c94fc9c2f5..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-22 +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 785ab3cc9b510..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-22 +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 5e309c9df351b..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-22 +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 0d41a58b46463..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-22 +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 f837c97cc9f00..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-22 +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 0e89309e8f298..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-22 +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 f419a515695a0..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-22 +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 10efc871c8616..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-22 +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 dbb8f61abcad1..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-22 +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 b1c0b209258bd..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-22 +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.devdocs.json b/api_docs/kbn_coloring.devdocs.json index a62c386424a76..e8c0cba7b4c2c 100644 --- a/api_docs/kbn_coloring.devdocs.json +++ b/api_docs/kbn_coloring.devdocs.json @@ -667,8 +667,7 @@ "label": "makeColorWithAlpha", "description": [], "signature": [ - "(color: string, newAlpha: number) => ", - "Color" + "(color: string, newAlpha: number) => chroma.Color" ], "path": "packages/kbn-coloring/src/color_manipulation/index.ts", "deprecated": false, diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 7d3bf8f9d84d0..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-22 +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 a811eb8e79a21..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-22 +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 e0d51c953032b..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-22 +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.devdocs.json b/api_docs/kbn_config_schema.devdocs.json index a4d1c926d9f23..4d82048910c62 100644 --- a/api_docs/kbn_config_schema.devdocs.json +++ b/api_docs/kbn_config_schema.devdocs.json @@ -1433,6 +1433,122 @@ ], "returnComment": [], "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.offeringBasedSchema", + "type": "Function", + "tags": [], + "label": "offeringBasedSchema", + "description": [ + "\nHelper to apply different validations depending on whether Kibana is running the Serverless or Traditional offering.\n" + ], + "signature": [ + "(opts: { serverless?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + " | undefined; traditional?: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + " | undefined; options?: ", + "TypeOptions", + " | undefined; }) => ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "" + ], + "path": "packages/kbn-config-schema/src/helpers/offering_based_schema.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.offeringBasedSchema.$1", + "type": "Object", + "tags": [], + "label": "opts", + "description": [], + "path": "packages/kbn-config-schema/src/helpers/offering_based_schema.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.offeringBasedSchema.$1.serverless", + "type": "Object", + "tags": [], + "label": "serverless", + "description": [], + "signature": [ + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + " | undefined" + ], + "path": "packages/kbn-config-schema/src/helpers/offering_based_schema.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.offeringBasedSchema.$1.traditional", + "type": "Object", + "tags": [], + "label": "traditional", + "description": [], + "signature": [ + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + " | undefined" + ], + "path": "packages/kbn-config-schema/src/helpers/offering_based_schema.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/config-schema", + "id": "def-common.offeringBasedSchema.$1.options", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "TypeOptions", + " | undefined" + ], + "path": "packages/kbn-config-schema/src/helpers/offering_based_schema.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false } ], "interfaces": [ diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 0898dcd5177bd..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 135 | 3 | 133 | 18 | +| 140 | 3 | 137 | 18 | ## Common diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index d735dff753a0c..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-22 +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 bee0a38ed3048..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-22 +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 36aeb8f6cd566..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-22 +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 9f9b0a9d35cc0..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-22 +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 e508c6eb3b3a8..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-22 +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 1d45f071691d3..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-22 +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 3949481f6b726..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-22 +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 bd91cdaefddd7..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-22 +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 65014f6fe8016..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-22 +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 7d76c2c9274a1..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-22 +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 e314184cf738d..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-22 +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.devdocs.json b/api_docs/kbn_core_application_browser.devdocs.json index 3a19d55a1ffda..20496e028aadf 100644 --- a/api_docs/kbn_core_application_browser.devdocs.json +++ b/api_docs/kbn_core_application_browser.devdocs.json @@ -1170,14 +1170,14 @@ "plugin": "@kbn/core-application-browser-internal", "path": "packages/core/application/core-application-browser-internal/src/ui/app_container.tsx" }, - { - "plugin": "@kbn/core-application-browser-mocks", - "path": "packages/core/application/core-application-browser-mocks/src/application_service.mock.ts" - }, { "plugin": "management", "path": "src/plugins/management/public/application.tsx" }, + { + "plugin": "@kbn/core-application-browser-mocks", + "path": "packages/core/application/core-application-browser-mocks/src/application_service.mock.ts" + }, { "plugin": "fleet", "path": "x-pack/plugins/fleet/public/applications/integrations/index.tsx" diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 5738b67634cde..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-22 +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 d34650d5edaa0..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-22 +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 d7628edda262f..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-22 +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 ed51de509dbb3..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-22 +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 4a5ed52963133..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-22 +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 883a14233541b..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-22 +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 f0abbde5d32f8..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-22 +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 9fb3ac5346b72..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-22 +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 1184608d871a6..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-22 +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 baa170bb092cb..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-22 +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 bab3f98d24b06..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-22 +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 95ef7613a7c7d..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-22 +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 ca7c8062fe44b..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-22 +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 93198937f495a..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-22 +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 45ce6da80243d..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-22 +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 6029ae3bec1ae..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-22 +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 c3fb562af09a6..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-22 +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 44787d809e41f..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-22 +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 cddfc058a76c8..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-22 +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 e6f8f6378478c..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-22 +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 b9cbc965f520e..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-22 +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 8d43d7789c997..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-22 +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 7d3e23a4d805e..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-22 +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 119d01620ecdd..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-22 +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 4084726f875c6..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-22 +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 517fd2062e9ba..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-22 +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 1de5704f3c5be..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-22 +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 598737203fd25..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-22 +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 16702a8ca7ade..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-22 +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 cd1144b2d852c..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-22 +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 0908266c2819a..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-22 +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 33961abadd7c8..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-22 +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 47bee0498cc58..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-22 +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 de24e2a453cbf..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-22 +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 9997a15df84bf..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-22 +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 06998e395141a..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-22 +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 c0d20f10d34d1..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-22 +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 ff77c423b5434..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-22 +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 17f5e711d82cf..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-22 +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 5fbd5caf660d4..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-22 +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 b0d55b5453f9e..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-22 +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 d2bcc01cfae66..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-22 +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 693855766d831..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-22 +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 24dc11b0df6f3..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-22 +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 49404516a0f49..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-22 +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 39f45e628ed96..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-22 +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 1ed93378e090b..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-22 +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 130c639198d1c..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-22 +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 f6e610241dd4b..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-22 +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 640440f8b0b5a..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-22 +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 dfcd60cf89c99..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-22 +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 c8936bb5a25d6..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-22 +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 e8f7f7a0946bb..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-22 +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 421bf787efb71..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-22 +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 5e630a3512a2d..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-22 +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 e807b3d1ca973..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-22 +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 e97bcffec84dc..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-22 +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 9f79da75560e3..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-22 +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 462ac1aeed8e8..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-22 +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 eb71465ccc80b..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-22 +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 0a379933fad32..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-22 +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 12c82a00d44cd..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-22 +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.devdocs.json b/api_docs/kbn_core_http_router_server_mocks.devdocs.json index 8dbc1fe6e57a7..929989bc0c910 100644 --- a/api_docs/kbn_core_http_router_server_mocks.devdocs.json +++ b/api_docs/kbn_core_http_router_server_mocks.devdocs.json @@ -80,7 +80,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"access\"> | undefined; access: \"internal\" | \"public\"; enableQueryVersion?: boolean | undefined; }" + ", \"access\"> | undefined; access: \"public\" | \"internal\"; enableQueryVersion?: boolean | undefined; }" ], "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts", "deprecated": false, diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 463f6013fe2ec..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-22 +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 7cdd8448f1dce..646cf9fd1bb02 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -3473,15 +3473,15 @@ }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/get.ts" + "path": "x-pack/plugins/actions/server/routes/connector/get_all/get_all.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/get_all.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", @@ -3787,6 +3851,10 @@ "plugin": "indexManagement", "path": "x-pack/plugins/index_management/server/routes/api/indices/register_list_route.ts" }, + { + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/server/routes/api/indices/register_get_route.ts" + }, { "plugin": "indexManagement", "path": "x-pack/plugins/index_management/server/routes/api/templates/register_get_routes.ts" @@ -4303,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/find_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/find_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/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/read_list_index_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/read_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/read_list_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/read_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" @@ -4392,204 +4404,108 @@ "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/rule_monitoring/api/detection_engine_health/get_cluster_health/get_cluster_health_route.ts" + "plugin": "serverlessSearch", + "path": "x-pack/plugins/serverless_search/server/routes/api_key_routes.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": "serverlessSearch", + "path": "x-pack/plugins/serverless_search/server/routes/indices_routes.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": "serverlessSearch", + "path": "x-pack/plugins/serverless_search/server/routes/connectors_routes.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": "serverlessSearch", + "path": "x-pack/plugins/serverless_search/server/routes/connectors_routes.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": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/app.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": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/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/rule_management/api/rules/filters/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/rule_management/api/rules/read_rule/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/rule_management/api/tags/read_tags/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/detection_engine/fleet_integrations/api/get_installed_integrations/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/detection_engine/rule_exceptions/api/find_exception_references/route.ts" + "plugin": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/restore.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/read_index_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/routes/signals/get_signals_migration_status_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/routes/privileges/read_privileges_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/timeline/routes/timelines/get_timeline/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/timelines/get_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/timelines/resolve_timeline/index.ts" + "plugin": "stackConnectors", + "path": "x-pack/plugins/stack_connectors/server/routes/get_well_known_email_service.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/draft_timelines/get_draft_timelines/index.ts" + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/server/server.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/telemetry/telemetry_detection_rules_preview_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/index/read_alerts_index_exists_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/endpoint/routes/resolver.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/app.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": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/cloud_backup_status.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/index_status/index.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/cluster_upgrade_status.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/tags/routes/get_tags_by_name.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/risk_engine/routes/risk_engine_status_route.ts" - }, - { - "plugin": "serverlessSearch", - "path": "x-pack/plugins/serverless_search/server/routes/api_key_routes.ts" - }, - { - "plugin": "serverlessSearch", - "path": "x-pack/plugins/serverless_search/server/routes/indices_routes.ts" - }, - { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/app.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/repositories.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/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/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": "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": "stackConnectors", - "path": "x-pack/plugins/stack_connectors/server/routes/get_well_known_email_service.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/batch_reindex_indices.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/app.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/cloud_backup_status.ts" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/cluster_upgrade_status.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/es_deprecations.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/es_deprecations.ts" }, { "plugin": "upgradeAssistant", @@ -4852,172 +4768,340 @@ "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": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/server.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": "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/get.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/get.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/get.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/get_all.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/get_all.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/get_all.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/aggregate_rules.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/aggregate_rules.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/aggregate_rules.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/aggregate_rules.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_action_error_log.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/data_streams/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_action_error_log.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/setup/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_flapping_settings.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_global_execution_kpi.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_global_execution_logs.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule_alert_summary.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule_alert_summary.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule_execution_log.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/get_rule_execution_log.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/get_rule_state.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/get_rule_state.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/get_rule_state.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/output/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule_tags.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/output/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule_tags.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/settings/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/get_rule_tags.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/app/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/health.test.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", + "path": "x-pack/plugins/actions/server/routes/get.test.ts" + }, + { + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/get.test.ts" + }, + { + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/get.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/aggregate_rules.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/aggregate_rules.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/aggregate_rules.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/aggregate_rules.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/find_rules.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_action_error_log.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_action_error_log.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_flapping_settings.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_global_execution_kpi.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_global_execution_logs.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_alert_summary.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_alert_summary.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_state.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_state.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_state.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_tags.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_tags.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/get_rule_tags.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/health.test.ts" }, { "plugin": "alerting", @@ -5075,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" @@ -5455,6 +5543,34 @@ "plugin": "remoteClusters", "path": "x-pack/plugins/remote_clusters/server/routes/api/get_route.test.ts" }, + { + "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/get_all/get_all.test.ts" + }, + { + "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" @@ -5608,268 +5724,72 @@ "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": "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/security_checkup/get_state.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/views/index.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/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/security_checkup/get_state.test.ts" - }, - { - "plugin": "security", - "path": "x-pack/plugins/security/server/routes/views/index.test.ts" + "plugin": "security", + "path": "x-pack/plugins/security/server/routes/views/index.test.ts" }, { "plugin": "security", @@ -6309,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" @@ -6489,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" @@ -6530,43 +6434,171 @@ "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": "indexManagement", - "path": "x-pack/plugins/index_management/server/routes/api/data_streams/register_delete_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts" }, { - "plugin": "indexManagement", + "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", + "path": "x-pack/plugins/index_management/server/routes/api/data_streams/register_delete_route.ts" + }, + { + "plugin": "indexManagement", "path": "x-pack/plugins/index_management/server/routes/api/data_streams/register_post_route.ts" }, { @@ -6649,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" @@ -7025,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/create_list_index_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/create_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/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/export_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/get_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/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" @@ -7130,437 +7110,441 @@ "path": "x-pack/plugins/searchprofiler/server/routes/profile.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": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/repositories.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" + "plugin": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/snapshots.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": "snapshotRestore", + "path": "x-pack/plugins/snapshot_restore/server/routes/api/restore.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring/api/detection_engine_health/setup/setup_health_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_actions_legacy/api/create_legacy_notification/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/routes/index/create_index_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/timeline/routes/timelines/create_timelines/index.ts" + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/server/server.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/import_timelines/index.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/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.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/prebuilt_rules/api/review_rule_installation/review_rule_installation_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/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_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/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.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/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts" + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/server/routes/cluster_settings.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts" + "plugin": "uptime", + "path": "x-pack/plugins/uptime/server/legacy_uptime/uptime_server.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/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/detection_engine/rule_management/api/rules/create_rule/route.ts" + "plugin": "watcher", + "path": "x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts" + "plugin": "watcher", + "path": "x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts" - }, + "plugin": "watcher", + "path": "x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts" + }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/route.ts" + "plugin": "grokdebugger", + "path": "x-pack/plugins/grokdebugger/server/lib/kibana_framework.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions/api/create_rule_exceptions/route.ts" + "plugin": "console", + "path": "src/plugins/console/server/routes/api/console/proxy/index.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts" + "plugin": "console", + "path": "src/plugins/console/server/routes/api/console/spec_definitions/index.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts" + "plugin": "contentManagement", + "path": "src/plugins/content_management/server/plugin.test.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts" + "plugin": "contentManagement", + "path": "src/plugins/content_management/server/plugin.test.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts" + "plugin": "contentManagement", + "path": "src/plugins/content_management/server/plugin.test.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts" + "plugin": "contentManagement", + "path": "src/plugins/content_management/server/plugin.test.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/export_timelines/index.ts" + "plugin": "contentManagement", + "path": "src/plugins/content_management/server/plugin.test.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/draft_timelines/clean_draft_timelines/index.ts" + "plugin": "contentManagement", + "path": "src/plugins/content_management/server/plugin.test.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts" + "plugin": "contentManagement", + "path": "src/plugins/content_management/server/plugin.test.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts" + "plugin": "contentManagement", + "path": "src/plugins/content_management/server/plugin.test.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/indices/delete_indices_route.ts" + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/server/routes/preview_scripted_field.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/routes/create_prebuilt_saved_objects.ts" + "plugin": "ftrApis", + "path": "src/plugins/ftr_apis/server/routes/kbn_client_so/bulk_delete.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/prebuilt_saved_objects/routes/delete_prebuilt_saved_objects.ts" + "plugin": "ftrApis", + "path": "src/plugins/ftr_apis/server/routes/kbn_client_so/create.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_score/onboarding/routes/install_risk_scores.ts" + "plugin": "ftrApis", + "path": "src/plugins/ftr_apis/server/routes/kbn_client_so/clean.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/exceptions/api/manage_exceptions/route.ts" + "plugin": "interactiveSetup", + "path": "src/plugins/interactive_setup/server/routes/configure.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/dashboards/routes/get_dashboards_by_tags.ts" + "plugin": "interactiveSetup", + "path": "src/plugins/interactive_setup/server/routes/enroll.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts" + "plugin": "interactiveSetup", + "path": "src/plugins/interactive_setup/server/routes/ping.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_score_preview_route.ts" + "plugin": "interactiveSetup", + "path": "src/plugins/interactive_setup/server/routes/verify.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_init_route.ts" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/routes/bulk_delete.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_enable_route.ts" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/routes/bulk_get.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_engine_disable_route.ts" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/routes/scroll_count.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/risk_engine/routes/risk_score_calculation_route.ts" + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/server/routes/run.ts" }, { - "plugin": "serverless", - "path": "x-pack/plugins/serverless/server/plugin.ts" + "plugin": "@kbn/core-http-router-server-internal", + "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts" }, { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts" + "plugin": "@kbn/core-http-router-server-internal", + "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts" }, { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/snapshots.ts" + "plugin": "@kbn/core-http-router-server-internal", + "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts" }, { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/restore.ts" + "plugin": "@kbn/core-http-router-server-internal", + "path": "packages/core/http/core-http-router-server-internal/src/router.ts" }, { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/policy.ts" + "plugin": "@kbn/core-http-router-server-internal", + "path": "packages/core/http/core-http-router-server-internal/src/router.ts" }, { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/policy.ts" + "plugin": "@kbn/core-http-router-server-internal", + "path": "packages/core/http/core-http-router-server-internal/src/router.test.ts" }, { - "plugin": "snapshotRestore", - "path": "x-pack/plugins/snapshot_restore/server/routes/api/policy.ts" + "plugin": "@kbn/core-http-router-server-internal", + "path": "packages/core/http/core-http-router-server-internal/src/router.test.ts" }, { - "plugin": "synthetics", - "path": "x-pack/plugins/synthetics/server/server.ts" + "plugin": "@kbn/core-http-router-server-internal", + "path": "packages/core/http/core-http-router-server-internal/src/router.test.ts" }, { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/update_index_settings.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/server/routes/cluster_settings.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "uptime", - "path": "x-pack/plugins/uptime/server/legacy_uptime/uptime_server.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "watcher", - "path": "x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "watcher", - "path": "x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "watcher", - "path": "x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "watcher", - "path": "x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "grokdebugger", - "path": "x-pack/plugins/grokdebugger/server/lib/kibana_framework.ts" + "plugin": "@kbn/core-http-server-internal", + "path": "packages/core/http/core-http-server-internal/src/http_server.test.ts" }, { - "plugin": "console", - "path": "src/plugins/console/server/routes/api/console/proxy/index.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/types.ts" }, { - "plugin": "console", - "path": "src/plugins/console/server/routes/api/console/spec_definitions/index.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, { - "plugin": "contentManagement", - "path": "src/plugins/content_management/server/plugin.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "contentManagement", - "path": "src/plugins/content_management/server/plugin.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "contentManagement", - "path": "src/plugins/content_management/server/plugin.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "contentManagement", - "path": "src/plugins/content_management/server/plugin.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "contentManagement", - "path": "src/plugins/content_management/server/plugin.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "contentManagement", - "path": "src/plugins/content_management/server/plugin.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "contentManagement", - "path": "src/plugins/content_management/server/plugin.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "contentManagement", - "path": "src/plugins/content_management/server/plugin.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/server/routes/preview_scripted_field.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "ftrApis", - "path": "src/plugins/ftr_apis/server/routes/kbn_client_so/bulk_delete.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "ftrApis", - "path": "src/plugins/ftr_apis/server/routes/kbn_client_so/create.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent_policy/index.ts" }, { - "plugin": "ftrApis", - "path": "src/plugins/ftr_apis/server/routes/kbn_client_so/clean.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" }, { - "plugin": "interactiveSetup", - "path": "src/plugins/interactive_setup/server/routes/configure.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" }, { - "plugin": "interactiveSetup", - "path": "src/plugins/interactive_setup/server/routes/enroll.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" }, { - "plugin": "interactiveSetup", - "path": "src/plugins/interactive_setup/server/routes/ping.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" }, { - "plugin": "interactiveSetup", - "path": "src/plugins/interactive_setup/server/routes/verify.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" }, { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/routes/bulk_delete.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/setup/index.ts" }, { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/routes/bulk_get.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/setup/index.ts" }, { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/routes/scroll_count.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "visTypeTimelion", - "path": "src/plugins/vis_types/timelion/server/routes/run.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "@kbn/core-http-router-server-internal", - "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "@kbn/core-http-router-server-internal", - "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "@kbn/core-http-router-server-internal", - "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "@kbn/core-http-router-server-internal", - "path": "packages/core/http/core-http-router-server-internal/src/router.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": "@kbn/core-http-router-server-internal", - "path": "packages/core/http/core-http-router-server-internal/src/router.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "@kbn/core-http-router-server-internal", - "path": "packages/core/http/core-http-router-server-internal/src/router.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "@kbn/core-http-router-server-internal", - "path": "packages/core/http/core-http-router-server-internal/src/router.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "@kbn/core-http-router-server-internal", - "path": "packages/core/http/core-http-router-server-internal/src/router.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "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/routes/enrollment_api_key/index.ts" }, { - "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/routes/enrollment_api_key/index.ts" }, { - "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/routes/output/index.ts" }, { - "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/routes/output/index.ts" }, { - "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/routes/app/index.ts" }, { - "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/routes/app/index.ts" }, { - "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/routes/preconfiguration/index.ts" }, { - "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/routes/preconfiguration/index.ts" }, { - "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/routes/download_source/index.tsx" }, { - "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/routes/health_check/index.ts" }, { - "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/routes/fleet_server_hosts/index.ts" }, { - "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/routes/fleet_proxies/index.ts" }, { - "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/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" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/server.ts" - }, { "plugin": "actions", "path": "x-pack/plugins/actions/server/routes/create.test.ts" @@ -7729,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" @@ -8037,273 +8025,93 @@ "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": "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": "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", @@ -8623,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", @@ -8851,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/update_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/update_list_route.ts" - }, { "plugin": "logstash", "path": "x-pack/plugins/logstash/server/routes/pipeline/save.ts" @@ -8887,30 +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/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": "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" @@ -8988,12 +8764,60 @@ "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": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/server.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" }, { "plugin": "actions", @@ -9027,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" @@ -9080,80 +8908,28 @@ "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": "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", @@ -9382,52 +9158,36 @@ "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/patch_list_item_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/patch_timelines/index.ts" }, { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/patch_list_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/persist_favorite/index.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts" + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/notes/persist_note.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/patch_rule/route.ts" + "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/pinned_events/persist_pinned_event.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/patch_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/persist_favorite/index.ts" + "plugin": "enterpriseSearch", + "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/security.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/notes/persist_note.ts" + "plugin": "enterpriseSearch", + "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts" }, { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/timeline/routes/pinned_events/persist_pinned_event.ts" + "plugin": "enterpriseSearch", + "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts" }, { "plugin": "@kbn/core-http-router-server-internal", @@ -9442,12 +9202,16 @@ "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": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/server.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" }, { "plugin": "alerting", @@ -9502,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", @@ -9763,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" @@ -9775,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" @@ -9935,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/delete_list_index_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/delete_list_item_route.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/routes/delete_list_route.ts" - }, { "plugin": "logstash", "path": "x-pack/plugins/logstash/server/routes/pipeline/delete.ts" @@ -9967,34 +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/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": "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" @@ -10048,156 +9776,156 @@ "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": "securitySolution", - "path": "x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/server.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/delete.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/delete.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/delete.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/delete_rule.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/agent/index.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/delete_rule.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/delete_rule.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts" }, { - "plugin": "ecsDataQualityDashboard", - "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/output/index.ts" }, { - "plugin": "globalSearch", - "path": "x-pack/plugins/global_search/server/routes/index.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/download_source/index.tsx" }, { - "plugin": "ruleRegistry", - "path": "x-pack/plugins/rule_registry/server/routes/__mocks__/server.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_server_hosts/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/legacy/delete.test.ts" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/routes/fleet_proxies/index.ts" }, { - "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/legacy/delete.test.ts" + "plugin": "@kbn/core-http-router-server-mocks", + "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/legacy/delete.test.ts" + "path": "x-pack/plugins/actions/server/routes/delete.test.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/routes/legacy/delete.test.ts" + "path": "x-pack/plugins/actions/server/routes/delete.test.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/legacy/delete.test.ts" + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/delete.test.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/legacy/delete.test.ts" + "path": "x-pack/plugins/alerting/server/routes/delete_rule.test.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/legacy/delete.test.ts" + "path": "x-pack/plugins/alerting/server/routes/delete_rule.test.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/legacy/delete.test.ts" + "path": "x-pack/plugins/alerting/server/routes/delete_rule.test.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/maintenance_window/delete_maintenance_window.test.ts" + "plugin": "ecsDataQualityDashboard", + "path": "x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/maintenance_window/delete_maintenance_window.test.ts" + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/__mocks__/server.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/maintenance_window/delete_maintenance_window.test.ts" + "plugin": "globalSearch", + "path": "x-pack/plugins/global_search/server/routes/index.test.ts" }, { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/maintenance_window/delete_maintenance_window.test.ts" + "plugin": "ruleRegistry", + "path": "x-pack/plugins/rule_registry/server/routes/__mocks__/server.ts" }, { - "plugin": "remoteClusters", - "path": "x-pack/plugins/remote_clusters/server/routes/api/delete_route.test.ts" + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/legacy/delete.test.ts" }, { - "plugin": "crossClusterReplication", - "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/auto_follow_pattern/register_delete_route.test.ts" + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/legacy/delete.test.ts" }, { - "plugin": "spaces", - "path": "x-pack/plugins/spaces/server/routes/api/external/delete.test.ts" + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/legacy/delete.test.ts" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/types.ts" + { + "plugin": "actions", + "path": "x-pack/plugins/actions/server/routes/legacy/delete.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/legacy/delete.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/legacy/delete.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/epm/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/legacy/delete.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/package_policy/index.ts" + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/legacy/delete.test.ts" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/routes/agent/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/enrollment_api_key/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/enrollment_api_key/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/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", @@ -11599,7 +11327,7 @@ "label": "access", "description": [], "signature": [ - "\"internal\" | \"public\"" + "\"public\" | \"internal\"" ], "path": "packages/core/http/core-http-server/src/router/request.ts", "deprecated": false, @@ -12703,7 +12431,7 @@ "\nDefines intended request origin of the route:\n- public. The route is public, declared stable and intended for external access.\n In the future, may require an incomming request to contain a specified header.\n- internal. The route is internal and intended for internal access only.\n\nDefaults to 'internal' If not declared," ], "signature": [ - "\"internal\" | \"public\" | undefined" + "\"public\" | \"internal\" | undefined" ], "path": "packages/core/http/core-http-server/src/router/route.ts", "deprecated": false, @@ -13797,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" @@ -13857,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" @@ -14074,16 +13866,160 @@ "path": "x-pack/plugins/ml/server/routes/management.ts" }, { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_config.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/live_query/get_live_query_details_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/live_query/get_live_query_results_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/live_query/find_live_query_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/status/create_status_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policies.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policy.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_status_for_agent_policy.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_package_policies.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agents.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_details.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/pack/find_pack_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/pack/read_pack_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/privileges_check/privileges_check_route.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/asset/get_assets_status_route.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": "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": "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": "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": "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": "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": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/find_rules/route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/filters/route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/read_rule/route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/tags/read_tags/route.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/details.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/state.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/audit_log.ts" }, { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_config.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/list.ts" }, { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_last_reported.ts" + "plugin": "@kbn/core-http-router-server-mocks", + "path": "packages/core/http/core-http-router-server-mocks/src/versioned_router.mock.ts" }, { "plugin": "logsShared", @@ -14193,118 +14129,6 @@ "plugin": "maps", "path": "x-pack/plugins/maps/server/routes.ts" }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/live_query/get_live_query_details_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/live_query/get_live_query_results_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/live_query/find_live_query_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/status/create_status_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policies.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policy.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_status_for_agent_policy.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_package_policies.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agents.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_details.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/pack/find_pack_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/pack/read_pack_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/privileges_check/privileges_check_route.ts" - }, - { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/asset/get_assets_status_route.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/details.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/state.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/audit_log.ts" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/server/endpoint/routes/actions/list.ts" - }, { "plugin": "sessionView", "path": "x-pack/plugins/session_view/server/routes/alerts_route.ts" @@ -14325,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" @@ -14508,7 +14328,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"access\"> | undefined; access: \"internal\" | \"public\"; enableQueryVersion?: boolean | undefined; }" + ", \"access\"> | undefined; access: \"public\" | \"internal\"; enableQueryVersion?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -14550,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", @@ -14577,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" @@ -14618,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", @@ -14649,14 +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": "transform", "path": "x-pack/plugins/transform/server/routes/api/transforms.ts" @@ -14676,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": [], @@ -14704,7 +14568,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"access\"> | undefined; access: \"internal\" | \"public\"; enableQueryVersion?: boolean | undefined; }" + ", \"access\"> | undefined; access: \"public\" | \"internal\"; enableQueryVersion?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -14745,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" @@ -14786,60 +14646,120 @@ "path": "src/plugins/data_views/server/rest_api_routes/public/swap_references.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts" + "plugin": "dataViews", + "path": "src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts" + }, + { + "plugin": "bfetch", + "path": "src/plugins/bfetch/server/plugin.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/server/search/routes/session.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/server/search/routes/session.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/server/search/routes/session.ts" + }, + { + "plugin": "data", + "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/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": "bfetch", - "path": "src/plugins/bfetch/server/plugin.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_index/create_list_index_route.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/search/routes/session.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list_item/create_list_item_route.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/search/routes/session.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/list/create_list_route.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/search/routes/session.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/duplicate_exception_list_route.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/search/routes/session.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/server/routes/export_exception_list_route.ts" }, { - "plugin": "data", - "path": "src/plugins/data/server/search/routes/search.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", @@ -15134,80 +15054,80 @@ "path": "x-pack/plugins/ml/server/routes/alerting.ts" }, { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts" }, { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_opt_in.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts" }, { - "plugin": "telemetry", - "path": "src/plugins/telemetry/server/routes/telemetry_usage_stats.ts" + "plugin": "osquery", + "path": "x-pack/plugins/osquery/server/routes/pack/create_pack_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/asset/update_assets_route.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/detection_engine/prebuilt_rules/api/review_rule_installation/review_rule_installation_route.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/custom_elements/create.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/review_rule_upgrade/review_rule_upgrade_route.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/shareables/zip.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_installation/perform_rule_installation_route.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/workpad/create.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/server/routes/workpad/import.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": "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_rule_health/get_rule_health_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_space_health/get_space_health_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/setup/setup_health_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_management/api/rules/bulk_actions/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/bulk_create_rules/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/bulk_delete_rules/route.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/create_rule/route.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/export_rules/route.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/pack/create_pack_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts" }, { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/server/routes/asset/update_assets_route.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/coverage_overview/route.ts" }, { "plugin": "securitySolution", @@ -15253,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" @@ -15372,7 +15352,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"access\"> | undefined; access: \"internal\" | \"public\"; enableQueryVersion?: boolean | undefined; }" + ", \"access\"> | undefined; access: \"public\" | \"internal\"; enableQueryVersion?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -15413,6 +15393,22 @@ "deprecated": false, "trackAdoption": true, "references": [ + { + "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/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts" + }, + { + "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" @@ -15456,7 +15452,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"access\"> | undefined; access: \"internal\" | \"public\"; enableQueryVersion?: boolean | undefined; }" + ", \"access\"> | undefined; access: \"public\" | \"internal\"; enableQueryVersion?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -15497,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" @@ -15529,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" @@ -15561,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" @@ -15581,14 +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": "@kbn/core-http-router-server-internal", "path": "packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_router.ts" @@ -15632,7 +15660,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"access\"> | undefined; access: \"internal\" | \"public\"; enableQueryVersion?: boolean | undefined; }" + ", \"access\"> | undefined; access: \"public\" | \"internal\"; enableQueryVersion?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -18116,7 +18144,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"access\"> | undefined; access: \"internal\" | \"public\"; enableQueryVersion?: boolean | undefined; }" + ", \"access\"> | undefined; access: \"public\" | \"internal\"; enableQueryVersion?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, @@ -18186,7 +18214,7 @@ "section": "def-common.RouteConfigOptions", "text": "RouteConfigOptions" }, - ", \"access\"> | undefined; access: \"internal\" | \"public\"; enableQueryVersion?: boolean | undefined; }" + ", \"access\"> | undefined; access: \"public\" | \"internal\"; enableQueryVersion?: boolean | undefined; }" ], "path": "packages/core/http/core-http-server/src/versioning/types.ts", "deprecated": false, diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 437e44d218051..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-22 +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 b51a5c58ddd5e..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-22 +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 270418054f48c..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-22 +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 f62926869cafc..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-22 +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 a35b76e4bf7ac..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-22 +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 262fc4813ec93..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-22 +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 90dce34c1e78f..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-22 +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 7bc85ebe38982..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-22 +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 2785456382182..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-22 +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 e26b1cf1d159f..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-22 +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 ba4aaeaf73778..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-22 +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.devdocs.json b/api_docs/kbn_core_lifecycle_browser.devdocs.json index 731dd471e31c9..fce341ae312bd 100644 --- a/api_docs/kbn_core_lifecycle_browser.devdocs.json +++ b/api_docs/kbn_core_lifecycle_browser.devdocs.json @@ -613,10 +613,6 @@ "plugin": "visualizations", "path": "src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx" }, - { - "plugin": "observability", - "path": "x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_definitions.ts" - }, { "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx" diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index 71352de1d3b98..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-22 +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 7235cede5536f..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-22 +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 b37fe3970cf1c..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-22 +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 bb0a34fbe9a77..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-22 +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 434b2dda89893..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-22 +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 854d6796811ae..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-22 +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 e2ad1d9356d64..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-22 +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 fbe52c0e81eac..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-22 +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 d7dc3c275c481..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-22 +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 0fd264172a6f8..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-22 +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 aa290423ed3d6..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-22 +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 b50ba05b37b6c..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-22 +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 5d81169930a4c..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-22 +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 7904a5fa1086a..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-22 +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 76a62c6dad652..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-22 +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 ccb8ec6d417ae..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-22 +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 8a8d18e1bb486..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-22 +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 fece750d65614..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-22 +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 d7a0cf3dbf534..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-22 +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 190b0e4ce0166..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-22 +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 7a2809ea024e4..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-22 +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 b9257319b2399..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-22 +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 0202eee61e7f3..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-22 +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 e5877e7a7539c..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-22 +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 8ee8e06bca2a8..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-22 +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 4ca945ba522d3..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-22 +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 3523f56c827fd..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-22 +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 bed9f92e1eb0f..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-22 +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 43baf16adf79d..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-22 +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 fffb674f170a2..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-22 +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 46b891629a363..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-22 +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 ea30520ff12a6..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-22 +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 5a351c5484d66..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-22 +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 48ec82b90fe8b..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-22 +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 8ccd20de9a425..94d374afbba24 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json @@ -65,6 +65,22 @@ "plugin": "@kbn/core", "path": "src/core/public/index.ts" }, + { + "plugin": "cases", + "path": "x-pack/plugins/cases/common/ui/types.ts" + }, + { + "plugin": "cases", + "path": "x-pack/plugins/cases/common/ui/types.ts" + }, + { + "plugin": "cases", + "path": "x-pack/plugins/cases/common/ui/types.ts" + }, + { + "plugin": "cases", + "path": "x-pack/plugins/cases/common/ui/types.ts" + }, { "plugin": "spaces", "path": "x-pack/plugins/spaces/public/legacy_urls/types.ts" @@ -121,22 +137,6 @@ "plugin": "lens", "path": "x-pack/plugins/lens/public/types.ts" }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/common/ui/types.ts" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/common/ui/types.ts" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/common/ui/types.ts" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/common/ui/types.ts" - }, { "plugin": "maps", "path": "x-pack/plugins/maps/public/map_attribute_service.ts" @@ -1054,10 +1054,6 @@ "plugin": "@kbn/core-saved-objects-browser-internal", "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_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": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/helpers/create_source.ts" @@ -1078,6 +1074,10 @@ "plugin": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/helpers/save_with_confirmation.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": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/saved_object.test.ts" @@ -1269,14 +1269,14 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/core-saved-objects-browser-mocks", - "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/saved_objects_service.mock.ts" - }, { "plugin": "home", "path": "src/plugins/home/public/application/components/home_app.js" }, + { + "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" @@ -1378,10 +1378,6 @@ "plugin": "@kbn/core-saved-objects-browser-internal", "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_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": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/helpers/build_saved_object.ts" @@ -1390,6 +1386,10 @@ "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" @@ -1623,10 +1623,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/core-saved-objects-browser-mocks", - "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/saved_objects_service.mock.ts" - }, { "plugin": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/helpers/find_object_by_title.ts" @@ -1636,8 +1632,8 @@ "path": "src/plugins/presentation_util/public/services/dashboards/dashboards_service.ts" }, { - "plugin": "observability", - "path": "x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_definitions.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": "dashboardEnhanced", @@ -1727,14 +1723,14 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/core-saved-objects-browser-mocks", - "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/saved_objects_service.mock.ts" - }, { "plugin": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/helpers/initialize_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": "dashboardEnhanced", "path": "x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/components/collect_config_container.tsx" @@ -3008,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", @@ -3024,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 3a7502daf62fa..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-22 +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 5727e00e06d62..89f29c9e91e81 100644 --- a/api_docs/kbn_core_saved_objects_api_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_server.devdocs.json @@ -2294,22 +2294,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.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": "@kbn/core-saved-objects-api-server-internal", "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/internal_utils.ts" @@ -2322,6 +2306,18 @@ "plugin": "@kbn/core-saved-objects-server-internal", "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, { "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" @@ -2371,20 +2367,8 @@ "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": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, { "plugin": "osquery", @@ -2474,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" @@ -2513,6 +2517,10 @@ { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/packages/get.test.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.test.ts" } ] }, @@ -2636,31 +2644,31 @@ }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", @@ -2786,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" @@ -2822,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" @@ -3255,10 +3263,6 @@ "plugin": "@kbn/core-saved-objects-api-server-internal", "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_create.ts" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" - }, { "plugin": "@kbn/core-saved-objects-api-server-internal", "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/test_helpers/repository.test.common.ts" @@ -7938,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" @@ -8024,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 256af90de496a..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-22 +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 16e9c56e59bd1..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-22 +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 8e85ce16d0104..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-22 +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 20253dcfaedd8..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-22 +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.devdocs.json b/api_docs/kbn_core_saved_objects_browser.devdocs.json index 487ebe0921108..c36309dcf903d 100644 --- a/api_docs/kbn_core_saved_objects_browser.devdocs.json +++ b/api_docs/kbn_core_saved_objects_browser.devdocs.json @@ -33,6 +33,10 @@ "deprecated": true, "trackAdoption": false, "references": [ + { + "plugin": "@kbn/core", + "path": "src/core/server/index.ts" + }, { "plugin": "@kbn/core-lifecycle-browser", "path": "packages/core/lifecycle/core-lifecycle-browser/src/core_start.ts" @@ -88,10 +92,6 @@ { "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", - "path": "src/core/server/index.ts" } ], "children": [ diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 5d2e7ab785cdd..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-22 +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 d2af4605a8702..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-22 +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 1787663a86ee6..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-22 +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 413c658b8baf4..34f58a56a00b1 100644 --- a/api_docs/kbn_core_saved_objects_common.devdocs.json +++ b/api_docs/kbn_core_saved_objects_common.devdocs.json @@ -1046,20 +1046,192 @@ "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" }, { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" + "plugin": "@kbn/core", + "path": "src/core/types/index.ts" }, { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" }, { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" }, { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/types.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/types.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" + }, + { + "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" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" + }, + { + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/common/types.ts" + }, + { + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/common/types.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" + }, + { + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/lib/find_relationships.test.ts" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/lib/find_relationships.test.ts" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/lib/find_relationships.test.ts" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/server/lib/find_relationships.test.ts" + }, + { + "plugin": "@kbn/core-saved-objects-api-server", + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts" + }, + { + "plugin": "@kbn/core-saved-objects-api-server", + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts" + }, + { + "plugin": "@kbn/core-saved-objects-api-server", + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts" + }, + { + "plugin": "@kbn/core-saved-objects-api-server", + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/import/errors.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/import/errors.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/import/lib/regenerate_ids.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/import/lib/regenerate_ids.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + }, + { + "plugin": "@kbn/core-saved-objects-import-export-server-internal", + "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" }, { "plugin": "@kbn/core-saved-objects-api-browser", @@ -1098,20 +1270,20 @@ "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" }, { - "plugin": "@kbn/core-saved-objects-api-server", - "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" }, { - "plugin": "@kbn/core-saved-objects-api-server", - "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" }, { - "plugin": "@kbn/core-saved-objects-api-server", - "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" }, { - "plugin": "@kbn/core-saved-objects-api-server", - "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" }, { "plugin": "@kbn/core-saved-objects-browser-internal", @@ -1270,216 +1442,44 @@ "path": "packages/core/saved-objects/core-saved-objects-browser-mocks/src/simple_saved_object.mock.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/import/errors.ts" - }, - { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/import/errors.ts" - }, - { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/import/lib/regenerate_ids.ts" - }, - { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/import/lib/regenerate_ids.ts" + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" + "plugin": "@kbn/core-ui-settings-server-internal", + "path": "packages/core/ui-settings/core-ui-settings-server-internal/src/saved_objects/transforms.test.ts" }, { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" - }, - { - "plugin": "@kbn/core-saved-objects-import-export-server-internal", - "path": "packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/export/apply_export_transforms.ts" - }, - { - "plugin": "@kbn/core", - "path": "src/core/types/index.ts" - }, - { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" - }, - { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" - }, - { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/types.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/types.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, - { - "plugin": "lists", - "path": "x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" - }, - { - "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" - }, - { - "plugin": "upgradeAssistant", - "path": "x-pack/plugins/upgrade_assistant/common/types.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/lib/find_relationships.test.ts" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/lib/find_relationships.test.ts" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/lib/find_relationships.test.ts" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/server/lib/find_relationships.test.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.test.ts" - }, - { - "plugin": "@kbn/core-ui-settings-server-internal", - "path": "packages/core/ui-settings/core-ui-settings-server-internal/src/saved_objects/transforms.test.ts" - }, - { - "plugin": "@kbn/core-ui-settings-server-internal", - "path": "packages/core/ui-settings/core-ui-settings-server-internal/src/saved_objects/transforms.test.ts" + "plugin": "@kbn/core-ui-settings-server-internal", + "path": "packages/core/ui-settings/core-ui-settings-server-internal/src/saved_objects/transforms.test.ts" }, { "plugin": "@kbn/core-ui-settings-server-internal", @@ -1519,6 +1519,10 @@ "deprecated": true, "trackAdoption": false, "references": [ + { + "plugin": "@kbn/core", + "path": "src/core/types/index.ts" + }, { "plugin": "@kbn/core", "path": "src/core/public/index.ts" @@ -1554,10 +1558,6 @@ { "plugin": "advancedSettings", "path": "src/plugins/advanced_settings/public/management_app/lib/to_editable_config.ts" - }, - { - "plugin": "@kbn/core", - "path": "src/core/types/index.ts" } ], "initialIsOpen": false @@ -1575,6 +1575,18 @@ "deprecated": true, "trackAdoption": false, "references": [ + { + "plugin": "@kbn/core", + "path": "src/core/types/index.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/common/types/modules.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/common/types/modules.ts" + }, { "plugin": "@kbn/core", "path": "src/core/public/index.ts" @@ -1742,18 +1754,6 @@ { "plugin": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/helpers/save_with_confirmation.test.ts" - }, - { - "plugin": "@kbn/core", - "path": "src/core/types/index.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/common/types/modules.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/common/types/modules.ts" } ], "initialIsOpen": false @@ -1784,11 +1784,11 @@ "references": [ { "plugin": "@kbn/core", - "path": "src/core/public/index.ts" + "path": "src/core/types/index.ts" }, { "plugin": "@kbn/core", - "path": "src/core/types/index.ts" + "path": "src/core/public/index.ts" } ], "initialIsOpen": false @@ -1807,824 +1807,824 @@ "trackAdoption": false, "references": [ { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/create.ts" + "plugin": "@kbn/core", + "path": "src/core/types/index.ts" }, { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/create.ts" + "plugin": "kibanaUtils", + "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" }, { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_update.ts" + "plugin": "kibanaUtils", + "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" }, { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_update.ts" + "plugin": "kibanaUtils", + "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" }, { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/update.ts" + "plugin": "kibanaUtils", + "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" }, { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/update.ts" + "plugin": "kibanaUtils", + "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" }, { - "plugin": "@kbn/core", - "path": "src/core/public/index.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/expression_functions/expression_function.ts" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/types.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/expression_functions/expression_function.ts" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/types.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/expression_functions/expression_function.ts" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/types.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/service/expressions_services.ts" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/types.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/service/expressions_services.ts" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/types.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/service/expressions_services.ts" }, { - "plugin": "savedObjects", - "path": "src/plugins/saved_objects/public/types.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/service/expressions_services.ts" }, { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/services/types/record.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/executor/executor.ts" }, { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/services/types/record.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/executor/executor.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts" + "plugin": "expressions", + "path": "src/plugins/expressions/common/executor/executor.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts" + "plugin": "data", + "path": "src/plugins/data/common/query/filters/persistable_state.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts" + "plugin": "data", + "path": "src/plugins/data/common/query/filters/persistable_state.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" + "plugin": "data", + "path": "src/plugins/data/common/query/filters/persistable_state.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" + "plugin": "data", + "path": "src/plugins/data/common/query/persistable_state.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" + "plugin": "data", + "path": "src/plugins/data/common/query/persistable_state.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" + "plugin": "data", + "path": "src/plugins/data/common/query/persistable_state.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx" + "plugin": "embeddable", + "path": "src/plugins/embeddable/common/lib/migrate_base_input.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx" + "plugin": "embeddable", + "path": "src/plugins/embeddable/common/lib/migrate_base_input.ts" }, { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx" + "plugin": "embeddable", + "path": "src/plugins/embeddable/common/lib/migrate_base_input.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx" + "plugin": "embeddable", + "path": "src/plugins/embeddable/common/lib/inject.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx" + "plugin": "embeddable", + "path": "src/plugins/embeddable/common/lib/inject.ts" }, { - "plugin": "eventAnnotation", - "path": "src/plugins/event_annotation/public/event_annotation_service/service.tsx" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" }, { - "plugin": "eventAnnotation", - "path": "src/plugins/event_annotation/public/event_annotation_service/service.tsx" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" }, { - "plugin": "eventAnnotation", - "path": "src/plugins/event_annotation/public/event_annotation_service/service.tsx" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/persistence/saved_object_store.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/persistence/saved_object_store.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/persistence/saved_object_store.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/state_management/selectors.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/options_list/options_list_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/state_management/selectors.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/options_list/options_list_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/state_management/selectors.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/options_list/options_list_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/range_slider/range_slider_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/range_slider/range_slider_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/range_slider/range_slider_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/time_slider/time_slider_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/time_slider/time_slider_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/time_slider/time_slider_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/control_group/control_group_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/utils.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/control_group/control_group_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/utils.ts" + "plugin": "controls", + "path": "src/plugins/controls/common/control_group/control_group_persistable_state.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/utils.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/utils.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/components/connected/tag_list.tsx" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/components/connected/tag_list.tsx" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/visualizations/xy/visualization.tsx" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/visualizations/xy/visualization.tsx" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_enhancement.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_enhancement.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx" + "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/common/migrations/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/common/migrations/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/common/migrations/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/common/migrations/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/common/migrations/references.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/types.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/public/map_attribute_service.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/saved_workspace_references.ts" + "plugin": "maps", + "path": "x-pack/plugins/maps/public/map_attribute_service.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/saved_workspace_references.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/saved_workspace_references.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/types/persistence.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_map.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/types/persistence.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_map.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.test.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_search.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.test.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_search.ts" }, { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.test.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.ts" }, { - "plugin": "dashboard", - "path": "src/plugins/dashboard/common/bwc/types.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.ts" }, { - "plugin": "dashboard", - "path": "src/plugins/dashboard/common/bwc/types.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/embeddable.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" + "plugin": "canvas", + "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/embeddable.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" + "plugin": "dashboardEnhanced", + "path": "x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" + "plugin": "dashboardEnhanced", + "path": "x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" + "plugin": "dashboardEnhanced", + "path": "x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/decorator/inject_tag_references.test.ts" + "plugin": "uiActionsEnhanced", + "path": "src/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/decorator/inject_tag_references.test.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/references.test.ts" }, { - "plugin": "@kbn/core", - "path": "src/core/types/index.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/references.test.ts" }, { - "plugin": "kibanaUtils", - "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" }, { - "plugin": "kibanaUtils", - "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" }, { - "plugin": "kibanaUtils", - "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" }, { - "plugin": "kibanaUtils", - "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" }, { - "plugin": "kibanaUtils", - "path": "src/plugins/kibana_utils/common/persistable_state/types.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/expression_functions/expression_function.ts" + "plugin": "globalSearchProviders", + "path": "x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.test.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/expression_functions/expression_function.ts" + "plugin": "globalSearchProviders", + "path": "x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.test.ts" }, { "plugin": "expressions", - "path": "src/plugins/expressions/common/expression_functions/expression_function.ts" + "path": "src/plugins/expressions/common/executor/executor.test.ts" }, { "plugin": "expressions", - "path": "src/plugins/expressions/common/service/expressions_services.ts" + "path": "src/plugins/expressions/common/executor/executor.test.ts" }, { "plugin": "expressions", - "path": "src/plugins/expressions/common/service/expressions_services.ts" + "path": "src/plugins/expressions/common/executor/executor.test.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/service/expressions_services.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/create.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/service/expressions_services.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/create.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/executor/executor.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_update.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/executor/executor.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_update.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/executor/executor.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/update.ts" }, { - "plugin": "data", - "path": "src/plugins/data/common/query/filters/persistable_state.ts" + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/update.ts" }, { - "plugin": "data", - "path": "src/plugins/data/common/query/filters/persistable_state.ts" + "plugin": "@kbn/core", + "path": "src/core/public/index.ts" }, { - "plugin": "data", - "path": "src/plugins/data/common/query/filters/persistable_state.ts" + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/types.ts" }, { - "plugin": "data", - "path": "src/plugins/data/common/query/persistable_state.ts" + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/types.ts" }, { - "plugin": "data", - "path": "src/plugins/data/common/query/persistable_state.ts" + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/types.ts" }, { - "plugin": "data", - "path": "src/plugins/data/common/query/persistable_state.ts" + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/types.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/types.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" + "plugin": "savedObjects", + "path": "src/plugins/saved_objects/public/types.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/services/types/record.ts" }, { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/services/types/record.ts" }, { - "plugin": "embeddable", - "path": "src/plugins/embeddable/common/lib/migrate_base_input.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts" }, { - "plugin": "embeddable", - "path": "src/plugins/embeddable/common/lib/migrate_base_input.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts" }, { - "plugin": "embeddable", - "path": "src/plugins/embeddable/common/lib/migrate_base_input.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualization_references/saved_visualization_references.ts" }, { - "plugin": "embeddable", - "path": "src/plugins/embeddable/common/lib/inject.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" }, { - "plugin": "embeddable", - "path": "src/plugins/embeddable/common/lib/inject.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" }, { "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" + "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" }, { "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" + "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" }, { "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" + "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" }, { "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" + "path": "src/plugins/visualizations/public/utils/saved_visualize_utils.ts" }, { "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" + "path": "src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx" }, { "plugin": "visualizations", - "path": "src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" + "path": "src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/options_list/options_list_persistable_state.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/options_list/options_list_persistable_state.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/options_list/options_list_persistable_state.ts" + "plugin": "visualizations", + "path": "src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/range_slider/range_slider_persistable_state.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/range_slider/range_slider_persistable_state.ts" + "plugin": "savedObjectsTagging", + "path": "x-pack/plugins/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/range_slider/range_slider_persistable_state.ts" + "plugin": "eventAnnotation", + "path": "src/plugins/event_annotation/public/event_annotation_service/service.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/time_slider/time_slider_persistable_state.ts" + "plugin": "eventAnnotation", + "path": "src/plugins/event_annotation/public/event_annotation_service/service.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/time_slider/time_slider_persistable_state.ts" + "plugin": "eventAnnotation", + "path": "src/plugins/event_annotation/public/event_annotation_service/service.tsx" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/time_slider/time_slider_persistable_state.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/persistence/saved_object_store.ts" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/control_group/control_group_persistable_state.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/persistence/saved_object_store.ts" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/control_group/control_group_persistable_state.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/persistence/saved_object_store.ts" }, { - "plugin": "controls", - "path": "src/plugins/controls/common/control_group/control_group_persistable_state.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/state_management/selectors.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/state_management/selectors.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/state_management/selectors.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/utils.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/components/connected/tag_list.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/utils.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/components/connected/tag_list.tsx" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/utils.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/utils.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_enhancement.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_enhancement.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" + "path": "x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/common/embeddable_factory/index.ts" + "path": "x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/common/migrations/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/common/migrations/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/visualizations/xy/visualization.tsx" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/common/migrations/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/visualizations/xy/visualization.tsx" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/common/migrations/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/common/migrations/references.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/public/map_attribute_service.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/public/map_attribute_service.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_lens.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_map.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_map.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_search.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_search.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/saved_visualization.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/embeddable.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "canvas", - "path": "x-pack/plugins/canvas/canvas_plugin_src/functions/external/embeddable.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/types.ts" }, { - "plugin": "dashboardEnhanced", - "path": "x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts" + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/saved_workspace_references.ts" }, { - "plugin": "dashboardEnhanced", - "path": "x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts" + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/saved_workspace_references.ts" }, { - "plugin": "dashboardEnhanced", - "path": "x-pack/plugins/dashboard_enhanced/common/drilldowns/dashboard_drilldown/dashboard_drilldown_persistable_state.ts" + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/saved_workspace_references.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts" + "plugin": "graph", + "path": "x-pack/plugins/graph/public/types/persistence.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts" + "plugin": "graph", + "path": "x-pack/plugins/graph/public/types/persistence.ts" }, { - "plugin": "uiActionsEnhanced", - "path": "src/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.test.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/references.test.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.test.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/references.test.ts" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.test.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" + "plugin": "dashboard", + "path": "src/plugins/dashboard/common/bwc/types.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" + "plugin": "dashboard", + "path": "src/plugins/dashboard/common/bwc/types.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/public/utils.test.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" }, { - "plugin": "savedObjectsTagging", - "path": "x-pack/plugins/saved_objects_tagging/common/test_utils/index.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" }, { - "plugin": "globalSearchProviders", - "path": "x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.test.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" }, { - "plugin": "globalSearchProviders", - "path": "x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.test.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/executor/executor.test.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/decorator/extract_tag_references.test.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/executor/executor.test.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/decorator/inject_tag_references.test.ts" }, { - "plugin": "expressions", - "path": "src/plugins/expressions/common/executor/executor.test.ts" + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/decorator/inject_tag_references.test.ts" }, { "plugin": "lens", diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index e83d133f7abfb..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-22 +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 074c73bf582c1..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-22 +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 7c06907f01386..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-22 +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 ac4d31f6439e6..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-22 +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 2797085c4ae07..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-22 +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 706b7e0a90e51..1853a66e3f1b5 100644 --- a/api_docs/kbn_core_saved_objects_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_server.devdocs.json @@ -5759,22 +5759,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "@kbn/core-saved-objects-api-browser", - "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" - }, - { - "plugin": "@kbn/core-saved-objects-browser-internal", - "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.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": "@kbn/core-saved-objects-api-server-internal", "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/internal_utils.ts" @@ -5787,6 +5771,18 @@ "plugin": "@kbn/core-saved-objects-server-internal", "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/legacy_import_export/lib/import_dashboards.ts" }, + { + "plugin": "@kbn/core-saved-objects-api-browser", + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, + { + "plugin": "@kbn/core-saved-objects-browser-internal", + "path": "packages/core/saved-objects/core-saved-objects-browser-internal/src/simple_saved_object.ts" + }, { "plugin": "home", "path": "src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/saved_objects.ts" @@ -5836,20 +5832,8 @@ "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": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts" }, { "plugin": "osquery", @@ -5939,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" @@ -5978,6 +5982,10 @@ { "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/epm/packages/get.test.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/epm/kibana/assets/install.test.ts" } ] }, @@ -6101,31 +6109,31 @@ }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", - "path": "x-pack/plugins/actions/server/actions_client.ts" + "path": "x-pack/plugins/actions/server/actions_client/actions_client.ts" }, { "plugin": "actions", @@ -6251,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" @@ -6287,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" @@ -8639,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, @@ -9611,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 @@ -10217,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[]" @@ -10547,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" @@ -10568,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", @@ -10591,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 27f722ea5557c..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-22 +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 99711bfb96cb0..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-22 +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 db035524c1adb..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-22 +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 c36dc4d28e158..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-22 +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 22b5b60521b8f..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-22 +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 39ed1ed1fcfe9..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-22 +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 f15e87ff20fe8..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-22 +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 c860646b9abc8..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-22 +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 70d5ec3b98379..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-22 +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 3904b9de8e90e..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-22 +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 22c7fbc536a2f..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-22 +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 abfa1ee5e5563..6631202ad7012 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.devdocs.json +++ b/api_docs/kbn_core_test_helpers_kbn_server.devdocs.json @@ -234,6 +234,74 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-test-helpers-kbn-server", + "id": "def-common.createTestServerlessInstances", + "type": "Function", + "tags": [ + "note" + ], + "label": "createTestServerlessInstances", + "description": [ + "\nSee docs in {@link TestUtils}. This function provides the same utilities but\nconfigured for serverless.\n" + ], + "signature": [ + "({\n adjustTimeout,\n}: { adjustTimeout: (timeout: number) => void; }) => ", + "TestServerlessUtils" + ], + "path": "packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-test-helpers-kbn-server", + "id": "def-common.createTestServerlessInstances.$1", + "type": "Object", + "tags": [], + "label": "{\n adjustTimeout,\n}", + "description": [], + "path": "packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-test-helpers-kbn-server", + "id": "def-common.createTestServerlessInstances.$1.adjustTimeout", + "type": "Function", + "tags": [], + "label": "adjustTimeout", + "description": [], + "signature": [ + "(timeout: number) => void" + ], + "path": "packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-test-helpers-kbn-server", + "id": "def-common.createTestServerlessInstances.$1.adjustTimeout.$1", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number" + ], + "path": "packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-test-helpers-kbn-server", "id": "def-common.createTestServers", @@ -688,6 +756,52 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-test-helpers-kbn-server", + "id": "def-common.TestServerlessESUtils", + "type": "Type", + "tags": [], + "label": "TestServerlessESUtils", + "description": [], + "signature": [ + "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, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-test-helpers-kbn-server", + "id": "def-common.TestServerlessKibanaUtils", + "type": "Type", + "tags": [], + "label": "TestServerlessKibanaUtils", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-test-helpers-kbn-server", + "scope": "common", + "docId": "kibKbnCoreTestHelpersKbnServerPluginApi", + "section": "def-common.TestKibanaUtils", + "text": "TestKibanaUtils" + } + ], + "path": "packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "objects": [ diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 3093f6854cbb5..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-22 +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'; @@ -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 | |-------------------|-----------|------------------------|-----------------| -| 55 | 1 | 49 | 0 | +| 61 | 1 | 54 | 1 | ## Common 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 aff3c50cd477b..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-22 +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 a1608bcba2800..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-22 +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 fe4cbb1a4efda..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-22 +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 54d108a479b76..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-22 +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 3e3a1dba67339..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-22 +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 0e12cff8b06a3..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-22 +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 a48616a42fdfd..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-22 +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 8d0a414c5f20b..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-22 +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 a6ee2815950e0..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-22 +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.devdocs.json b/api_docs/kbn_core_ui_settings_server_internal.devdocs.json index 19b0355b0870b..f78d51ab09830 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.devdocs.json +++ b/api_docs/kbn_core_ui_settings_server_internal.devdocs.json @@ -306,7 +306,7 @@ "section": "def-common.ConditionalType", "text": "ConditionalType" }, - "; }>" + "; }>" ], "path": "packages/core/ui-settings/core-ui-settings-server-internal/src/ui_settings_config.ts", "deprecated": false, diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 29044a6529dfc..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-22 +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 bddeca4ea7c44..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-22 +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 f358ebb530589..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-22 +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 c6e0f49f09fd3..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-22 +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 377e7d6375dc1..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-22 +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 fe4c945cc76b6..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-22 +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 919b63add7907..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-22 +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 9a2db35b29629..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-22 +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 b92ca0fb181c3..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-22 +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 92c720f6e1197..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-22 +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 3930552ff5b11..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-22 +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 81a58ad3ed141..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-22 +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 99b470fdac1f6..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-22 +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 fca79a30d8f08..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-22 +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 2aa1e34707e25..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-22 +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 6b1cee5736481..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-22 +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 db6e8db29479a..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-22 +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 be7aa4661f51a..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-22 +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 eecdacc4c7145..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\"" + "\"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 5da0301e738fc..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-22 +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.devdocs.json b/api_docs/kbn_default_nav_analytics.devdocs.json index 82c562b654726..17b5e0d62238c 100644 --- a/api_docs/kbn_default_nav_analytics.devdocs.json +++ b/api_docs/kbn_default_nav_analytics.devdocs.json @@ -145,13 +145,10 @@ { "parentPluginId": "@kbn/default-nav-analytics", "id": "def-common.defaultNavigation.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "packages/default-nav/analytics/default_navigation.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index 342cb9174cc37..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.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 | |-------------------|-----------|------------------------|-----------------| -| 7 | 1 | 7 | 0 | +| 7 | 0 | 7 | 0 | ## Common diff --git a/api_docs/kbn_default_nav_devtools.devdocs.json b/api_docs/kbn_default_nav_devtools.devdocs.json index 7ae5c10bbfc30..dbdf1885d3139 100644 --- a/api_docs/kbn_default_nav_devtools.devdocs.json +++ b/api_docs/kbn_default_nav_devtools.devdocs.json @@ -131,13 +131,10 @@ { "parentPluginId": "@kbn/default-nav-devtools", "id": "def-common.defaultNavigation.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "packages/default-nav/devtools/default_navigation.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index 0bb313ec04730..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.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 | |-------------------|-----------|------------------------|-----------------| -| 7 | 1 | 7 | 0 | +| 7 | 0 | 7 | 0 | ## Common diff --git a/api_docs/kbn_default_nav_management.devdocs.json b/api_docs/kbn_default_nav_management.devdocs.json index 36be968bcbfc7..17e0d18c97a95 100644 --- a/api_docs/kbn_default_nav_management.devdocs.json +++ b/api_docs/kbn_default_nav_management.devdocs.json @@ -145,13 +145,10 @@ { "parentPluginId": "@kbn/default-nav-management", "id": "def-common.defaultNavigation.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "packages/default-nav/management/default_navigation.ts", "deprecated": false, "trackAdoption": false @@ -175,7 +172,7 @@ "label": "children", "description": [], "signature": [ - "[{ id: \"root\"; title: string; children: [{ link: \"monitoring\"; }]; }, { id: \"integration_management\"; title: any; children: [{ link: \"integrations\"; }, { link: \"fleet\"; }, { link: \"osquery\"; }]; }, { id: \"stack_management\"; title: any; children: [{ id: \"ingest\"; title: any; children: [{ link: \"management:ingest_pipelines\"; }, { link: \"management:pipelines\"; }]; }, { id: \"data\"; title: any; children: [{ link: \"management:index_management\"; }, { link: \"management:transform\"; }]; }, { id: \"alerts_and_insights\"; title: any; children: [{ link: \"management:triggersActions\"; }, { link: \"management:cases\"; }, { link: \"management:triggersActionsConnectors\"; }, { link: \"management:jobsListLink\"; }]; }, { id: \"kibana\"; title: string; children: [{ link: \"management:dataViews\"; }, { link: \"management:objects\"; }, { link: \"management:tags\"; }, { link: \"management:spaces\"; }, { link: \"management:settings\"; }]; }]; }]" + "[{ id: \"root\"; title: string; children: [{ link: \"monitoring\"; }]; }, { id: \"integration_management\"; title: string; children: [{ link: \"integrations\"; }, { link: \"fleet\"; }, { link: \"osquery\"; }]; }, { id: \"stack_management\"; title: string; children: [{ id: \"ingest\"; title: string; children: [{ link: \"management:ingest_pipelines\"; }, { link: \"management:pipelines\"; }]; }, { id: \"data\"; title: string; children: [{ link: \"management:index_management\"; }, { link: \"management:transform\"; }]; }, { id: \"alerts_and_insights\"; title: string; children: [{ link: \"management:triggersActions\"; }, { link: \"management:cases\"; }, { link: \"management:triggersActionsConnectors\"; }, { link: \"management:jobsListLink\"; }]; }, { id: \"kibana\"; title: string; children: [{ link: \"management:dataViews\"; }, { link: \"management:objects\"; }, { link: \"management:tags\"; }, { link: \"management:spaces\"; }, { link: \"management:settings\"; }]; }]; }]" ], "path": "packages/default-nav/management/default_navigation.ts", "deprecated": false, diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index 7cfd864f1b649..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_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 | |-------------------|-----------|------------------------|-----------------| -| 7 | 1 | 7 | 0 | +| 7 | 0 | 7 | 0 | ## Common diff --git a/api_docs/kbn_default_nav_ml.devdocs.json b/api_docs/kbn_default_nav_ml.devdocs.json index 7c79c7686c12f..2b213eea008dc 100644 --- a/api_docs/kbn_default_nav_ml.devdocs.json +++ b/api_docs/kbn_default_nav_ml.devdocs.json @@ -145,13 +145,10 @@ { "parentPluginId": "@kbn/default-nav-ml", "id": "def-common.defaultNavigation.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "packages/default-nav/ml/default_navigation.ts", "deprecated": false, "trackAdoption": false @@ -175,7 +172,7 @@ "label": "children", "description": [], "signature": [ - "[{ title: string; id: \"root\"; children: [{ link: \"ml:overview\"; }, { link: \"ml:notifications\"; }]; }, { title: any; id: \"anomaly_detection\"; children: [{ title: any; link: \"ml:anomalyDetection\"; }, { link: \"ml:anomalyExplorer\"; }, { link: \"ml:singleMetricViewer\"; }, { link: \"ml:settings\"; }]; }, { id: \"data_frame_analytics\"; title: any; children: [{ title: string; link: \"ml:dataFrameAnalytics\"; }, { link: \"ml:resultExplorer\"; }, { link: \"ml:analyticsMap\"; }]; }, { id: \"model_management\"; title: any; children: [{ link: \"ml:nodesOverview\"; }, { link: \"ml:nodes\"; }]; }, { id: \"data_visualizer\"; title: any; children: [{ title: any; link: \"ml:fileUpload\"; }, { title: any; link: \"ml:indexDataVisualizer\"; }]; }, { id: \"aiops_labs\"; title: any; children: [{ link: \"ml:logRateAnalysis\"; }, { link: \"ml:logPatternAnalysis\"; }, { link: \"ml:changePointDetections\"; }]; }]" + "[{ title: string; id: \"root\"; children: [{ link: \"ml:overview\"; }, { link: \"ml:notifications\"; }]; }, { title: string; id: \"anomaly_detection\"; children: [{ title: string; link: \"ml:anomalyDetection\"; }, { link: \"ml:anomalyExplorer\"; }, { link: \"ml:singleMetricViewer\"; }, { link: \"ml:settings\"; }]; }, { id: \"data_frame_analytics\"; title: string; children: [{ title: string; link: \"ml:dataFrameAnalytics\"; }, { link: \"ml:resultExplorer\"; }, { link: \"ml:analyticsMap\"; }]; }, { id: \"model_management\"; title: string; children: [{ link: \"ml:nodesOverview\"; }, { link: \"ml:nodes\"; }]; }, { id: \"data_visualizer\"; title: string; children: [{ title: string; link: \"ml:fileUpload\"; }, { title: string; link: \"ml:indexDataVisualizer\"; }]; }, { id: \"aiops_labs\"; title: string; children: [{ link: \"ml:logRateAnalysis\"; }, { link: \"ml:logPatternAnalysis\"; }, { link: \"ml:changePointDetections\"; }]; }]" ], "path": "packages/default-nav/ml/default_navigation.ts", "deprecated": false, diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index 4fc68f28e288e..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 7 | 1 | 7 | 0 | +| 7 | 0 | 7 | 0 | ## Common diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index e080061b46594..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-22 +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 7d11e9ee4b475..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-22 +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 af2e8cb04fdea..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-22 +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 e35dfe02816a2..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-22 +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 63d1b38143a1f..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-22 +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 68cda4d7b4e6b..724a581015e7e 100644 --- a/api_docs/kbn_doc_links.devdocs.json +++ b/api_docs/kbn_doc_links.devdocs.json @@ -202,7 +202,7 @@ "label": "console", "description": [], "signature": [ - "{ readonly guide: string; }" + "{ readonly guide: string; readonly serverlessGuide: string; }" ], "path": "packages/kbn-doc-links/src/types.ts", "deprecated": false, @@ -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, @@ -840,7 +840,7 @@ "label": "fleet", "description": [], "signature": [ - "{ readonly beatsAgentComparison: string; readonly guide: string; readonly fleetServer: string; readonly fleetServerAddFleetServer: string; readonly settings: string; readonly settingsFleetServerHostSettings: string; readonly settingsFleetServerProxySettings: string; readonly troubleshooting: string; readonly elasticAgent: string; readonly datastreams: string; readonly datastreamsILM: string; readonly datastreamsNamingScheme: string; readonly datastreamsManualRollover: string; readonly datastreamsTSDS: string; readonly datastreamsTSDSMetrics: string; readonly installElasticAgent: string; readonly installElasticAgentStandalone: string; readonly packageSignatures: string; readonly upgradeElasticAgent: string; readonly learnMoreBlog: string; readonly apiKeysLearnMore: string; readonly onPremRegistry: string; readonly secureLogstash: string; readonly agentPolicy: string; readonly api: string; readonly uninstallAgent: string; }" + "{ readonly beatsAgentComparison: string; readonly guide: string; readonly fleetServer: string; readonly fleetServerAddFleetServer: string; readonly settings: string; readonly logstashSettings: string; readonly kafkaSettings: string; readonly settingsFleetServerHostSettings: string; readonly settingsFleetServerProxySettings: string; readonly troubleshooting: string; readonly elasticAgent: string; readonly datastreams: string; readonly datastreamsILM: string; readonly datastreamsNamingScheme: string; readonly datastreamsManualRollover: string; readonly datastreamsTSDS: string; readonly datastreamsTSDSMetrics: string; readonly installElasticAgent: string; readonly installElasticAgentStandalone: string; readonly packageSignatures: string; readonly upgradeElasticAgent: string; readonly learnMoreBlog: string; readonly apiKeysLearnMore: string; readonly onPremRegistry: string; readonly secureLogstash: string; readonly agentPolicy: string; readonly api: string; readonly uninstallAgent: string; }" ], "path": "packages/kbn-doc-links/src/types.ts", "deprecated": false, @@ -930,6 +930,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/doc-links", + "id": "def-common.DocLinks.serverlessClients", + "type": "Object", + "tags": [], + "label": "serverlessClients", + "description": [], + "signature": [ + "{ readonly goApiReference: string; readonly goGettingStarted: string; readonly httpApis: string; readonly httpApiReferences: string; readonly jsApiReference: string; readonly jsGettingStarted: string; readonly phpApiReference: string; readonly phpGettingStarted: string; readonly pythonApiReference: string; readonly pythonGettingStarted: string; readonly pythonReferences: string; readonly rubyApiReference: string; readonly rubyGettingStarted: string; }" + ], + "path": "packages/kbn-doc-links/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/doc-links", "id": "def-common.DocLinks.serverlessSearch", @@ -938,7 +952,7 @@ "label": "serverlessSearch", "description": [], "signature": [ - "{ readonly integrations: string; }" + "{ readonly gettingStartedExplore: string; readonly gettingStartedIngest: string; readonly gettingStartedSearch: string; readonly integrations: string; readonly integrationsBeats: string; readonly integrationsConnectorClient: string; readonly integrationsLogstash: 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 138dba0ac8a6b..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/docs](https://github.com/orgs/elastic/teams/docs) for question | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 72 | 0 | 72 | 2 | +| 73 | 0 | 73 | 2 | ## Common diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 77f8f8638e504..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-22 +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 50407e08c93ee..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-22 +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 acabfdcec5d54..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-22 +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 88b7649281502..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-22 +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.devdocs.json b/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json index 0015a2f6b419c..48c4823f73460 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json +++ b/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json @@ -11,7 +11,7 @@ "label": "DATA_QUALITY_PROMPT_CONTEXT_PILL", "description": [], "signature": [ - "(indexName: string) => any" + "(indexName: string) => string" ], "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", "deprecated": false, @@ -112,13 +112,10 @@ { "parentPluginId": "@kbn/ecs-data-quality-dashboard", "id": "def-public.DATA_QUALITY_PROMPT_CONTEXT_PILL_TOOLTIP", - "type": "Any", + "type": "string", "tags": [], "label": "DATA_QUALITY_PROMPT_CONTEXT_PILL_TOOLTIP", "description": [], - "signature": [ - "any" - ], "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", "deprecated": false, "trackAdoption": false, @@ -141,13 +138,10 @@ { "parentPluginId": "@kbn/ecs-data-quality-dashboard", "id": "def-public.DATA_QUALITY_SUGGESTED_USER_PROMPT", - "type": "Any", + "type": "string", "tags": [], "label": "DATA_QUALITY_SUGGESTED_USER_PROMPT", "description": [], - "signature": [ - "any" - ], "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/translations.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 6623f0d77836c..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-threat-hunting-investigations](https://github.com/org | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 13 | 2 | 5 | 0 | +| 13 | 0 | 5 | 0 | ## Client diff --git a/api_docs/kbn_elastic_assistant.devdocs.json b/api_docs/kbn_elastic_assistant.devdocs.json index 4485abc1850c8..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, 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 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<", @@ -350,6 +387,64 @@ } ], "interfaces": [ + { + "parentPluginId": "@kbn/elastic-assistant", + "id": "def-public.AssistantAvailability", + "type": "Interface", + "tags": [], + "label": "AssistantAvailability", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant", + "id": "def-public.AssistantAvailability.isAssistantEnabled", + "type": "boolean", + "tags": [], + "label": "isAssistantEnabled", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant", + "id": "def-public.AssistantAvailability.hasAssistantPrivilege", + "type": "boolean", + "tags": [], + "label": "hasAssistantPrivilege", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant", + "id": "def-public.AssistantAvailability.hasConnectorsAllPrivilege", + "type": "boolean", + "tags": [], + "label": "hasConnectorsAllPrivilege", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant", + "id": "def-public.AssistantAvailability.hasConnectorsReadPrivilege", + "type": "boolean", + "tags": [], + "label": "hasConnectorsReadPrivilege", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant", "id": "def-public.AssistantTelemetry", @@ -1074,13 +1169,10 @@ { "parentPluginId": "@kbn/elastic-assistant", "id": "def-public.ELASTIC_AI_ASSISTANT_TITLE", - "type": "Any", + "type": "string", "tags": [], "label": "ELASTIC_AI_ASSISTANT_TITLE", "description": [], - "signature": [ - "any" - ], "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/translations.ts", "deprecated": false, "trackAdoption": false, @@ -1121,13 +1213,10 @@ { "parentPluginId": "@kbn/elastic-assistant", "id": "def-public.WELCOME_CONVERSATION_TITLE", - "type": "Any", + "type": "string", "tags": [], "label": "WELCOME_CONVERSATION_TITLE", "description": [], - "signature": [ - "any" - ], "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/translations.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index ee0df955e86c8..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 77 | 2 | 58 | 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 5e9ff2e2100bf..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-22 +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 90a1e8492e20d..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-22 +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 fd19378e02a4a..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-22 +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 f52fafb8cfe10..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-22 +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.devdocs.json b/api_docs/kbn_event_annotation_common.devdocs.json index 54277c81fd4d3..8aeb9fd601424 100644 --- a/api_docs/kbn_event_annotation_common.devdocs.json +++ b/api_docs/kbn_event_annotation_common.devdocs.json @@ -543,13 +543,10 @@ { "parentPluginId": "@kbn/event-annotation-common", "id": "def-common.defaultAnnotationLabel", - "type": "Any", + "type": "string", "tags": [], "label": "defaultAnnotationLabel", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-event-annotation-common/util.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index 8f281ade51e16..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.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 | |-------------------|-----------|------------------------|-----------------| -| 39 | 1 | 39 | 0 | +| 39 | 0 | 39 | 0 | ## Common diff --git a/api_docs/kbn_event_annotation_components.devdocs.json b/api_docs/kbn_event_annotation_components.devdocs.json index 54b9e95eb01e1..64b85baf88e09 100644 --- a/api_docs/kbn_event_annotation_components.devdocs.json +++ b/api_docs/kbn_event_annotation_components.devdocs.json @@ -1052,7 +1052,7 @@ "section": "def-common.EventAnnotationGroupConfig", "text": "EventAnnotationGroupConfig" }, - ", \"annotations\" | \"ignoreGlobalFilters\" | \"indexPatternId\">[]; }) => ", + ", \"ignoreGlobalFilters\" | \"annotations\" | \"indexPatternId\">[]; }) => ", { "pluginId": "expressions", "scope": "common", @@ -1104,7 +1104,7 @@ "section": "def-common.EventAnnotationGroupConfig", "text": "EventAnnotationGroupConfig" }, - ", \"annotations\" | \"ignoreGlobalFilters\" | \"indexPatternId\">[]" + ", \"ignoreGlobalFilters\" | \"annotations\" | \"indexPatternId\">[]" ], "path": "packages/kbn-event-annotation-components/types.ts", "deprecated": false, @@ -1343,13 +1343,10 @@ { "parentPluginId": "@kbn/event-annotation-components", "id": "def-public.defaultAnnotationLabel", - "type": "Any", + "type": "string", "tags": [], "label": "defaultAnnotationLabel", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-event-annotation-common/util.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index 36ea81e316851..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 65 | 1 | 65 | 1 | +| 65 | 0 | 65 | 1 | ## Client diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index 4ab2b36c26b83..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-22 +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 4a5ce014311df..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-22 +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 352d265c053a9..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-22 +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 4c65b96e7af90..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-22 +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 86eb975123e88..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-22 +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 fa9a3a0b5355d..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-22 +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 852a9811f28d0..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-22 +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 317305554df04..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-22 +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 8ccb5f3625b37..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-22 +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 6b6ca35c01291..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-22 +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 3911f8ccf2912..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-22 +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 478fadf1ed8d1..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-22 +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 2d3a33ad484f7..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-22 +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 8079fe3178771..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-22 +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.devdocs.json b/api_docs/kbn_i18n.devdocs.json index 5cea6349dcdbc..a57c972d1826f 100644 --- a/api_docs/kbn_i18n.devdocs.json +++ b/api_docs/kbn_i18n.devdocs.json @@ -517,7 +517,7 @@ "section": "def-common.TranslateArguments", "text": "TranslateArguments" }, - ") => any" + ") => string" ], "path": "packages/kbn-i18n/index.ts", "deprecated": false, diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 1c6e9afc0f432..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-22 +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 4753a7602c6a9..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-22 +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 8c5f3bc5ccc61..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-22 +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 a766471cdd0c9..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-22 +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 fe1362a2e1af2..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-22 +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 4d29413493798..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-22 +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 8cabf7b62fcc1..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-22 +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 81cedbcee5a74..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-22 +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 f508da29caae5..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-22 +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 9e486150d13cd..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-22 +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 36909485c210b..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-22 +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 837ad6207d28f..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-22 +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 add0b2c4e4b62..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-22 +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 66750d32d7ce6..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-22 +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 1cc277fbdbc45..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-22 +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 6989bb8445f79..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-22 +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 a52cefa5cb2f0..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-22 +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 4fd56c20785f1..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-22 +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 76c2b386beda7..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-22 +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 3956c3bb40a25..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-22 +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 644521bc1b575..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-22 +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 c06e547ed26df..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-22 +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 7192147d32662..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-22 +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 382be4b18ea2f..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-22 +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 e2bfc0cad2bfa..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-22 +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.devdocs.json b/api_docs/kbn_ml_date_picker.devdocs.json index 37b14af61fb1b..69aa0e7997284 100644 --- a/api_docs/kbn_ml_date_picker.devdocs.json +++ b/api_docs/kbn_ml_date_picker.devdocs.json @@ -524,138 +524,25 @@ }, { "parentPluginId": "@kbn/ml-date-picker", - "id": "def-common.DatePickerDependencies.wrapWithTheme", - "type": "Function", + "id": "def-common.DatePickerDependencies.i18n", + "type": "Object", "tags": [], - "label": "wrapWithTheme", + "label": "i18n", "description": [ - "\nhelper to be used with notifications." + "\nInternationalisation service" ], "signature": [ - "(node: React.ReactNode, theme$: ", - "Observable", - "<", { - "pluginId": "@kbn/react-kibana-context-common", + "pluginId": "@kbn/core-i18n-browser", "scope": "common", - "docId": "kibKbnReactKibanaContextCommonPluginApi", - "section": "def-common.KibanaTheme", - "text": "KibanaTheme" - }, - ">) => JSX.Element" - ], - "path": "x-pack/packages/ml/date_picker/src/hooks/use_date_picker_context.tsx", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/ml-date-picker", - "id": "def-common.DatePickerDependencies.wrapWithTheme.$1", - "type": "CompoundType", - "tags": [], - "label": "node", - "description": [], - "signature": [ - "boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | null | undefined" - ], - "path": "src/plugins/kibana_react/public/theme.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/ml-date-picker", - "id": "def-common.DatePickerDependencies.wrapWithTheme.$2", - "type": "Object", - "tags": [], - "label": "theme$", - "description": [], - "signature": [ - "Observable", - "<", - { - "pluginId": "@kbn/react-kibana-context-common", - "scope": "common", - "docId": "kibKbnReactKibanaContextCommonPluginApi", - "section": "def-common.KibanaTheme", - "text": "KibanaTheme" - }, - ">" - ], - "path": "src/plugins/kibana_react/public/theme.tsx", - "deprecated": false, - "trackAdoption": false + "docId": "kibKbnCoreI18nBrowserPluginApi", + "section": "def-common.I18nStart", + "text": "I18nStart" } - ] - }, - { - "parentPluginId": "@kbn/ml-date-picker", - "id": "def-common.DatePickerDependencies.toMountPoint", - "type": "Function", - "tags": [], - "label": "toMountPoint", - "description": [ - "\nhelper to be used with notifications." - ], - "signature": [ - "(node: React.ReactNode, { theme$ }?: ", - { - "pluginId": "kibanaReact", - "scope": "public", - "docId": "kibKibanaReactPluginApi", - "section": "def-public.ToMountPointOptions", - "text": "ToMountPointOptions" - }, - ") => ", - { - "pluginId": "@kbn/core-mount-utils-browser", - "scope": "common", - "docId": "kibKbnCoreMountUtilsBrowserPluginApi", - "section": "def-common.MountPoint", - "text": "MountPoint" - }, - "" ], "path": "x-pack/packages/ml/date_picker/src/hooks/use_date_picker_context.tsx", "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/ml-date-picker", - "id": "def-common.DatePickerDependencies.toMountPoint.$1", - "type": "CompoundType", - "tags": [], - "label": "node", - "description": [], - "signature": [ - "boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | null | undefined" - ], - "path": "src/plugins/kibana_react/public/util/index.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/ml-date-picker", - "id": "def-common.DatePickerDependencies.toMountPoint.$2", - "type": "Object", - "tags": [], - "label": "__1", - "description": [], - "signature": [ - { - "pluginId": "kibanaReact", - "scope": "public", - "docId": "kibKibanaReactPluginApi", - "section": "def-public.ToMountPointOptions", - "text": "ToMountPointOptions" - } - ], - "path": "src/plugins/kibana_react/public/util/index.tsx", - "deprecated": false, - "trackAdoption": false - } - ] + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 26510920fb55f..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 52 | 0 | 4 | 0 | +| 47 | 0 | 0 | 0 | ## Common diff --git a/api_docs/kbn_ml_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index a9941ae75a008..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-22 +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 30ea003dd3069..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-22 +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 380a359c49e96..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-22 +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 dcdb40a2563f6..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-22 +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 ae82932c2d477..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-22 +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 449dac356fcbe..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-22 +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 9ba7230c4f974..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-22 +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 d81bd96fadfb2..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-22 +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 78f5536d2a603..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-22 +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 f028123b4e326..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-22 +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 10e38d630f1f5..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-22 +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 781f01593ee17..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-22 +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 f3e1a906e339c..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-22 +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 e38fd5c8d89b9..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-22 +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.devdocs.json b/api_docs/kbn_ml_trained_models_utils.devdocs.json index 78b0f58eaba25..4401041f76b06 100644 --- a/api_docs/kbn_ml_trained_models_utils.devdocs.json +++ b/api_docs/kbn_ml_trained_models_utils.devdocs.json @@ -40,13 +40,10 @@ { "parentPluginId": "@kbn/ml-trained-models-utils", "id": "def-common.BUILT_IN_MODEL_TYPE", - "type": "Any", + "type": "string", "tags": [], "label": "BUILT_IN_MODEL_TYPE", "description": [], - "signature": [ - "any" - ], "path": "x-pack/packages/ml/trained_models_utils/src/constants/trained_models.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index 5c4b808234317..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 8 | 1 | 8 | 0 | +| 8 | 0 | 8 | 0 | ## Common diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 73d34a5f758fc..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-22 +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 cceef607a016d..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-22 +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 a0d0b9909006b..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-22 +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 b885ef4e33397..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-22 +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 56501bb419d6d..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-22 +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 527cf7a229999..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-22 +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 7e9fae33d4c3a..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-22 +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 efef1122083d8..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-22 +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 d0fafbceaff08..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-22 +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 94dbac6a7460f..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-22 +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 c754b389ab158..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-22 +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 d73dfed0dceb2..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-22 +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 1f655867eb108..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-22 +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 b8c1c95ba27e1..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-22 +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 e70ef516ed832..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-22 +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 940f8819dbe40..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-22 +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 ec2e4a9005c7c..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-22 +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 ed105519a0fae..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-22 +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 9abc420933544..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-22 +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 cdc2b81aebbd0..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-22 +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 e404112a6e0c4..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-22 +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 380418dc220d8..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-22 +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.devdocs.json b/api_docs/kbn_reporting_common.devdocs.json index 0413d5a18cb0c..bb90486c2546c 100644 --- a/api_docs/kbn_reporting_common.devdocs.json +++ b/api_docs/kbn_reporting_common.devdocs.json @@ -137,7 +137,7 @@ "label": "humanFriendlyMessage", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "packages/kbn-reporting/common/errors.ts", "deprecated": false, @@ -593,7 +593,7 @@ "label": "humanFriendlyMessage", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "packages/kbn-reporting/common/errors.ts", "deprecated": false, @@ -879,7 +879,7 @@ "label": "humanFriendlyMessage", "description": [], "signature": [ - "() => any" + "() => string" ], "path": "packages/kbn-reporting/common/errors.ts", "deprecated": false, diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index 9dab892aad9c6..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-22 +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 318e2ba75a757..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-22 +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 35a77cb839a11..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-22 +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 b7dbb1c041e0c..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-22 +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 fe3c7d9146536..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-22 +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 5f1b06dd23303..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" @@ -54,43 +54,183 @@ }, { "parentPluginId": "@kbn/search-api-panels", - "id": "def-common.GithubLink", + "id": "def-common.getConsoleRequest", "type": "Function", "tags": [], - "label": "GithubLink", + "label": "getConsoleRequest", "description": [], "signature": [ - "({ label, href, http, pluginId }: React.PropsWithChildren<{ label: string; href: string; http: ", + "(code: keyof ", { - "pluginId": "@kbn/core-http-browser", + "pluginId": "@kbn/search-api-panels", "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" + "docId": "kibKbnSearchApiPanelsPluginApi", + "section": "def-common.LanguageDefinition", + "text": "LanguageDefinition" }, - "; pluginId: string; }>) => JSX.Element" + ") => string | undefined" ], - "path": "packages/kbn-search-api-panels/components/github_link.tsx", + "path": "packages/kbn-search-api-panels/utils.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/search-api-panels", - "id": "def-common.GithubLink.$1", + "id": "def-common.getConsoleRequest.$1", "type": "CompoundType", "tags": [], - "label": "{ label, href, http, pluginId }", + "label": "code", "description": [], "signature": [ - "React.PropsWithChildren<{ label: string; href: string; http: ", + "keyof ", { - "pluginId": "@kbn/core-http-browser", + "pluginId": "@kbn/search-api-panels", "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" + "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", + "type": "Function", + "tags": [], + "label": "getLanguageDefinitionCodeSnippet", + "description": [], + "signature": [ + "(language: Partial<", + { + "pluginId": "@kbn/search-api-panels", + "scope": "common", + "docId": "kibKbnSearchApiPanelsPluginApi", + "section": "def-common.LanguageDefinition", + "text": "LanguageDefinition" + }, + ">, key: keyof ", + { + "pluginId": "@kbn/search-api-panels", + "scope": "common", + "docId": "kibKbnSearchApiPanelsPluginApi", + "section": "def-common.LanguageDefinition", + "text": "LanguageDefinition" + }, + ", args: ", + { + "pluginId": "@kbn/search-api-panels", + "scope": "common", + "docId": "kibKbnSearchApiPanelsPluginApi", + "section": "def-common.LanguageDefinitionSnippetArguments", + "text": "LanguageDefinitionSnippetArguments" + }, + ") => string" + ], + "path": "packages/kbn-search-api-panels/utils.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.getLanguageDefinitionCodeSnippet.$1", + "type": "Object", + "tags": [], + "label": "language", + "description": [], + "signature": [ + "Partial<", + { + "pluginId": "@kbn/search-api-panels", + "scope": "common", + "docId": "kibKbnSearchApiPanelsPluginApi", + "section": "def-common.LanguageDefinition", + "text": "LanguageDefinition" }, - "; pluginId: string; }>" + ">" + ], + "path": "packages/kbn-search-api-panels/utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.getLanguageDefinitionCodeSnippet.$2", + "type": "CompoundType", + "tags": [], + "label": "key", + "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 + }, + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.getLanguageDefinitionCodeSnippet.$3", + "type": "Object", + "tags": [], + "label": "args", + "description": [], + "signature": [ + { + "pluginId": "@kbn/search-api-panels", + "scope": "common", + "docId": "kibKbnSearchApiPanelsPluginApi", + "section": "def-common.LanguageDefinitionSnippetArguments", + "text": "LanguageDefinitionSnippetArguments" + } + ], + "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.GithubLink", + "type": "Function", + "tags": [], + "label": "GithubLink", + "description": [], + "signature": [ + "({ 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, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.GithubLink.$1", + "type": "CompoundType", + "tags": [], + "label": "{ assetBasePath, label, href }", + "description": [], + "signature": [ + "React.PropsWithChildren<{ assetBasePath: string; label: string; href: string; }>" ], "path": "packages/kbn-search-api-panels/components/github_link.tsx", "deprecated": false, @@ -109,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, @@ -120,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" @@ -142,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, @@ -153,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" @@ -175,7 +315,7 @@ "label": "IntegrationsPanel", "description": [], "signature": [ - "({ docLinks, http, pluginId, }: React.PropsWithChildren<", + "({ docLinks, assetBasePath, }: React.PropsWithChildren<", { "pluginId": "@kbn/search-api-panels", "scope": "common", @@ -194,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<", @@ -224,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, @@ -235,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" @@ -443,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, @@ -476,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, @@ -574,6 +694,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.LanguageDefinition.github", + "type": "Object", + "tags": [], + "label": "github", + "description": [], + "signature": [ + "{ link: string; label: string; } | undefined" + ], + "path": "packages/kbn-search-api-panels/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/search-api-panels", "id": "def-common.LanguageDefinition.iconType", @@ -778,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 49db14f806dbd..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 58 | 1 | 58 | 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 353f5f947f7bc..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-22 +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 b6f6fc12979c3..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-22 +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 bc10dd050a379..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-22 +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 37dd3c56051a2..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-22 +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.devdocs.json b/api_docs/kbn_securitysolution_autocomplete.devdocs.json index fd3a4ca6431f9..436117f912a54 100644 --- a/api_docs/kbn_securitysolution_autocomplete.devdocs.json +++ b/api_docs/kbn_securitysolution_autocomplete.devdocs.json @@ -842,7 +842,7 @@ "label": "smallLists", "description": [], "signature": [ - "{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]" + "{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]" ], "path": "packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx", "deprecated": false, @@ -856,7 +856,7 @@ "label": "largeLists", "description": [], "signature": [ - "{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]" + "{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]" ], "path": "packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx", "deprecated": false, diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index f0b7dfdde66a1..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-22 +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 4cde6815cdc02..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-22 +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 10af0e60fdffa..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-22 +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 4119a04abaa4d..ffa1a41949e97 100644 --- a/api_docs/kbn_securitysolution_es_utils.devdocs.json +++ b/api_docs/kbn_securitysolution_es_utils.devdocs.json @@ -93,6 +93,58 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.createDataStream", + "type": "Function", + "tags": [], + "label": "createDataStream", + "description": [ + "\ncreates data stream" + ], + "signature": [ + "(esClient: ", + "ElasticsearchClient", + ", name: string) => Promise" + ], + "path": "packages/kbn-securitysolution-es-utils/src/create_data_stream/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.createDataStream.$1", + "type": "Object", + "tags": [], + "label": "esClient", + "description": [], + "signature": [ + "ElasticsearchClient" + ], + "path": "packages/kbn-securitysolution-es-utils/src/create_data_stream/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.createDataStream.$2", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-securitysolution-es-utils/src/create_data_stream/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-es-utils", "id": "def-common.decodeVersion", @@ -206,6 +258,58 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.deleteDataStream", + "type": "Function", + "tags": [], + "label": "deleteDataStream", + "description": [ + "\ndeletes data stream" + ], + "signature": [ + "(esClient: ", + "ElasticsearchClient", + ", name: string) => Promise" + ], + "path": "packages/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.deleteDataStream.$1", + "type": "Object", + "tags": [], + "label": "esClient", + "description": [], + "signature": [ + "ElasticsearchClient" + ], + "path": "packages/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.deleteDataStream.$2", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-es-utils", "id": "def-common.deleteIndexTemplate", @@ -447,6 +551,58 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.getDataStreamExists", + "type": "Function", + "tags": [], + "label": "getDataStreamExists", + "description": [ + "\nchecks if data stream exists" + ], + "signature": [ + "(esClient: ", + "ElasticsearchClient", + ", name: string) => Promise" + ], + "path": "packages/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.getDataStreamExists.$1", + "type": "Object", + "tags": [], + "label": "esClient", + "description": [], + "signature": [ + "ElasticsearchClient" + ], + "path": "packages/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.getDataStreamExists.$2", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-es-utils", "id": "def-common.getIndexAliases", @@ -3195,6 +3351,129 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.migrateToDataStream", + "type": "Function", + "tags": [], + "label": "migrateToDataStream", + "description": [ + "\nmigrate to data stream" + ], + "signature": [ + "(esClient: ", + "ElasticsearchClient", + ", name: string) => Promise" + ], + "path": "packages/kbn-securitysolution-es-utils/src/migrate_to_data_stream/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.migrateToDataStream.$1", + "type": "Object", + "tags": [], + "label": "esClient", + "description": [], + "signature": [ + "ElasticsearchClient" + ], + "path": "packages/kbn-securitysolution-es-utils/src/migrate_to_data_stream/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.migrateToDataStream.$2", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-securitysolution-es-utils/src/migrate_to_data_stream/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.putMappings", + "type": "Function", + "tags": [], + "label": "putMappings", + "description": [ + "\nupdate mappings of index" + ], + "signature": [ + "(esClient: ", + "ElasticsearchClient", + ", index: string, mappings: Record) => Promise" + ], + "path": "packages/kbn-securitysolution-es-utils/src/put_mappings/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.putMappings.$1", + "type": "Object", + "tags": [], + "label": "esClient", + "description": [], + "signature": [ + "ElasticsearchClient" + ], + "path": "packages/kbn-securitysolution-es-utils/src/put_mappings/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.putMappings.$2", + "type": "string", + "tags": [], + "label": "index", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-securitysolution-es-utils/src/put_mappings/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.putMappings.$3", + "type": "Object", + "tags": [], + "label": "mappings", + "description": [], + "signature": [ + "Record" + ], + "path": "packages/kbn-securitysolution-es-utils/src/put_mappings/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-es-utils", "id": "def-common.readIndex", @@ -3295,6 +3574,56 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.removePolicyFromIndex", + "type": "Function", + "tags": [], + "label": "removePolicyFromIndex", + "description": [], + "signature": [ + "(esClient: ", + "ElasticsearchClient", + ", index: string) => Promise" + ], + "path": "packages/kbn-securitysolution-es-utils/src/remove_policy_from_index/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.removePolicyFromIndex.$1", + "type": "Object", + "tags": [], + "label": "esClient", + "description": [], + "signature": [ + "ElasticsearchClient" + ], + "path": "packages/kbn-securitysolution-es-utils/src/remove_policy_from_index/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/securitysolution-es-utils", + "id": "def-common.removePolicyFromIndex.$2", + "type": "string", + "tags": [], + "label": "index", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-securitysolution-es-utils/src/remove_policy_from_index/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-es-utils", "id": "def-common.setIndexTemplate", @@ -3490,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 bb3bf5a90fe5b..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 68 | 0 | 62 | 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 54a88998dab7d..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\" | \"main\" | \"path\" | \"form\" | \"span\" | \"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\" | \"main\" | \"path\" | \"form\" | \"span\" | \"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\" | \"main\" | \"path\" | \"form\" | \"span\" | \"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\" | \"main\" | \"path\" | \"form\" | \"span\" | \"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 6dd9dc4996c9f..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-22 +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 801b08a382805..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-22 +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 f322b627d0596..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-22 +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 5a90e1e24eaf9..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-22 +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.devdocs.json b/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json index 5dc5e1d380969..e407327295855 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json +++ b/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json @@ -3905,7 +3905,7 @@ "label": "FoundAllListItemsSchema", "description": [], "signature": [ - "{ data: { _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; total: number; }" + "{ data: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; total: number; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/found_all_list_items_schema/index.ts", "deprecated": false, @@ -3950,7 +3950,7 @@ "label": "FoundListItemSchema", "description": [], "signature": [ - "{ cursor: string; data: { _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; page: number; per_page: number; total: number; }" + "{ cursor: string; data: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; page: number; per_page: number; total: number; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_item_schema/index.ts", "deprecated": false, @@ -3965,7 +3965,7 @@ "label": "FoundListsBySizeSchema", "description": [], "signature": [ - "{ largeLists: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; smallLists: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; }" + "{ largeLists: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; smallLists: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/found_lists_by_size_schema/index.ts", "deprecated": false, @@ -3980,7 +3980,7 @@ "label": "FoundListSchema", "description": [], "signature": [ - "{ cursor: string; data: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; page: number; per_page: number; total: number; }" + "{ cursor: string; data: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; page: number; per_page: number; total: number; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/found_list_schema/index.ts", "deprecated": false, @@ -4355,7 +4355,7 @@ "label": "ListArraySchema", "description": [], "signature": [ - "{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]" + "{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts", "deprecated": false, @@ -4400,7 +4400,7 @@ "label": "ListItemArraySchema", "description": [], "signature": [ - "{ _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]" + "{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts", "deprecated": false, @@ -4430,7 +4430,7 @@ "label": "ListItemSchema", "description": [], "signature": [ - "{ _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }" + "{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts", "deprecated": false, @@ -4460,7 +4460,7 @@ "label": "ListSchema", "description": [], "signature": [ - "{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }" + "{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts", "deprecated": false, @@ -4737,6 +4737,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.NullableMetaOrUndefined", + "type": "Type", + "tags": [], + "label": "NullableMetaOrUndefined", + "description": [], + "signature": [ + "object | null | undefined" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.OsType", @@ -5135,7 +5150,7 @@ "label": "SearchListItemArraySchema", "description": [], "signature": [ - "{ items: { _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; value: unknown; }[]" + "{ items: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; value: unknown; }[]" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.ts", "deprecated": false, @@ -5150,7 +5165,7 @@ "label": "SearchListItemSchema", "description": [], "signature": [ - "{ items: { _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; value: unknown; }" + "{ items: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; value: unknown; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/response/search_list_item_schema/index.ts", "deprecated": false, @@ -8182,6 +8197,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -8518,6 +8539,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -8590,6 +8617,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -8642,6 +8675,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -8714,6 +8753,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -9709,6 +9754,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -9775,6 +9826,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -9857,6 +9914,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -9933,6 +9996,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -10310,6 +10379,30 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.nullableMetaOrUndefined", + "type": "Object", + "tags": [], + "label": "nullableMetaOrUndefined", + "description": [], + "signature": [ + "UnionC", + "<[", + "UnionC", + "<[", + "ObjectC", + ", ", + "UndefinedC", + "]>, ", + "NullC", + "]>" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.osType", @@ -10765,6 +10858,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -10835,6 +10934,12 @@ "StringC", ", ", "UndefinedC", + "]>; '@timestamp': ", + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", "]>; created_at: ", "StringC", "; created_by: ", @@ -11083,6 +11188,42 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.timestamp", + "type": "Object", + "tags": [], + "label": "timestamp", + "description": [], + "signature": [ + "Type", + "" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.timestampOrUndefined", + "type": "Object", + "tags": [], + "label": "timestampOrUndefined", + "description": [], + "signature": [ + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", + "]>" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.total", diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 49b266f6f55e9..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-22 +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'; @@ -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 | |-------------------|-----------|------------------------|-----------------| -| 528 | 0 | 515 | 0 | +| 532 | 0 | 519 | 0 | ## Common diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 9ce64d1746c52..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-22 +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 6f2ee1e36ecf6..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-22 +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.devdocs.json b/api_docs/kbn_securitysolution_list_api.devdocs.json index 1a07636db6652..fa3108bcd8c04 100644 --- a/api_docs/kbn_securitysolution_list_api.devdocs.json +++ b/api_docs/kbn_securitysolution_list_api.devdocs.json @@ -317,7 +317,7 @@ "section": "def-common.DeleteListParams", "text": "DeleteListParams" }, - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" ], "path": "packages/kbn-securitysolution-list-api/src/list_api/index.ts", "deprecated": false, @@ -701,7 +701,7 @@ "section": "def-common.FindListsParams", "text": "FindListsParams" }, - ") => Promise<{ largeLists: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; smallLists: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; }>" + ") => Promise<{ largeLists: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; smallLists: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; }>" ], "path": "packages/kbn-securitysolution-list-api/src/list_api/index.ts", "deprecated": false, @@ -748,7 +748,7 @@ "section": "def-common.FindListsParams", "text": "FindListsParams" }, - ") => Promise<{ cursor: string; data: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; page: number; per_page: number; total: number; }>" + ") => Promise<{ cursor: string; data: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; page: number; per_page: number; total: number; }>" ], "path": "packages/kbn-securitysolution-list-api/src/list_api/index.ts", "deprecated": false, @@ -913,7 +913,7 @@ "section": "def-common.ImportListParams", "text": "ImportListParams" }, - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" ], "path": "packages/kbn-securitysolution-list-api/src/list_api/index.ts", "deprecated": false, diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index cfff83e47ccf4..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-22 +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 f691ec2fa0f08..c3f2279e6ccde 100644 --- a/api_docs/kbn_securitysolution_list_constants.devdocs.json +++ b/api_docs/kbn_securitysolution_list_constants.devdocs.json @@ -69,51 +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/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/constants.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", + "path": "x-pack/plugins/security_solution/public/management/pages/blocklist/services/blocklists_api_client.ts" }, { "plugin": "securitySolution", @@ -163,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" @@ -217,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", @@ -257,103 +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/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/view/utils.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/service_actions.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/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/public/management/pages/policy/view/policy_hooks.ts" }, { "plugin": "securitySolution", @@ -423,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" @@ -445,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", @@ -517,51 +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/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/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/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": "securitySolution", + "path": "x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/host_isolation_exceptions_api_client.ts" }, { "plugin": "lists", @@ -627,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" @@ -845,68 +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": "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", @@ -1068,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" @@ -1135,21 +1167,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/securitysolution-list-constants", - "id": "def-common.EXCEPTION_FILTER", - "type": "string", - "tags": [], - "label": "EXCEPTION_FILTER", - "description": [], - "signature": [ - "\"/internal/lists/_create_filter\"" - ], - "path": "packages/kbn-securitysolution-list-constants/index.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "@kbn/securitysolution-list-constants", "id": "def-common.EXCEPTION_LIST_ITEM_URL", @@ -1216,13 +1233,13 @@ }, { "parentPluginId": "@kbn/securitysolution-list-constants", - "id": "def-common.FIND_LISTS_BY_SIZE", + "id": "def-common.INTERNAL_EXCEPTION_FILTER", "type": "string", "tags": [], - "label": "FIND_LISTS_BY_SIZE", + "label": "INTERNAL_EXCEPTION_FILTER", "description": [], "signature": [ - "\"/internal/lists/_find_lists_by_size\"" + "\"/internal/lists/_create_filter\"" ], "path": "packages/kbn-securitysolution-list-constants/index.ts", "deprecated": false, @@ -1255,6 +1272,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-list-constants", + "id": "def-common.INTERNAL_FIND_LISTS_BY_SIZE", + "type": "string", + "tags": [], + "label": "INTERNAL_FIND_LISTS_BY_SIZE", + "description": [], + "signature": [ + "\"/internal/lists/_find_lists_by_size\"" + ], + "path": "packages/kbn-securitysolution-list-constants/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-list-constants", "id": "def-common.INTERNAL_LIST_URL", diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index e90bb418822fc..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-22 +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.devdocs.json b/api_docs/kbn_securitysolution_list_hooks.devdocs.json index 14c2ee5a4b122..a16b45f6a1c79 100644 --- a/api_docs/kbn_securitysolution_list_hooks.devdocs.json +++ b/api_docs/kbn_securitysolution_list_hooks.devdocs.json @@ -421,7 +421,7 @@ "section": "def-common.DeleteListParams", "text": "DeleteListParams" }, - ">], { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" + ">], { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" ], "path": "packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts", "deprecated": false, @@ -559,7 +559,7 @@ "section": "def-common.FindListsParams", "text": "FindListsParams" }, - ">], { cursor: string; data: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; page: number; per_page: number; total: number; }>" + ">], { cursor: string; data: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; page: number; per_page: number; total: number; }>" ], "path": "packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts", "deprecated": false, @@ -600,7 +600,7 @@ "section": "def-common.FindListsParams", "text": "FindListsParams" }, - ">], { largeLists: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; smallLists: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; }>" + ">], { largeLists: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; smallLists: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; }>" ], "path": "packages/kbn-securitysolution-list-hooks/src/use_find_lists_by_size/index.ts", "deprecated": false, @@ -641,7 +641,7 @@ "section": "def-common.ImportListParams", "text": "ImportListParams" }, - ">], { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" + ">], { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" ], "path": "packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts", "deprecated": false, diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 28bd4841879c5..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-22 +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.devdocs.json b/api_docs/kbn_securitysolution_list_utils.devdocs.json index 880b165fbb561..b47a7562eeffd 100644 --- a/api_docs/kbn_securitysolution_list_utils.devdocs.json +++ b/api_docs/kbn_securitysolution_list_utils.devdocs.json @@ -617,7 +617,7 @@ "section": "def-common.FormattedBuilderEntry", "text": "FormattedBuilderEntry" }, - ", newField: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }) => { index: number; updatedEntry: ", + ", newField: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }) => { index: number; updatedEntry: ", { "pluginId": "@kbn/securitysolution-list-utils", "scope": "common", @@ -664,7 +664,7 @@ "- newly selected list" ], "signature": [ - "{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }" + "{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }" ], "path": "packages/kbn-securitysolution-list-utils/src/helpers/index.ts", "deprecated": false, @@ -3326,13 +3326,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.doesNotExistOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false @@ -3407,13 +3404,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.doesNotMatchOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false @@ -3488,13 +3482,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.existsOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false @@ -3569,13 +3560,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.isInListOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false @@ -3650,13 +3638,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.isNotInListOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false @@ -3731,13 +3716,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.isNotOneOfOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false @@ -3812,13 +3794,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.isNotOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false @@ -3893,13 +3872,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.isOneOfOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false @@ -3974,13 +3950,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.isOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false @@ -4055,13 +4028,10 @@ { "parentPluginId": "@kbn/securitysolution-list-utils", "id": "def-common.matchesOperator.message", - "type": "Any", + "type": "string", "tags": [], "label": "message", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-list-utils/src/autocomplete_operators/index.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 970aab1522f14..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_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 | |-------------------|-----------|------------------------|-----------------| -| 207 | 10 | 160 | 0 | +| 207 | 0 | 160 | 0 | ## Common diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 5c07ef1ded446..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-22 +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 21fb3a335ccc5..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-22 +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 19d6d2a0a2340..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, @@ -520,13 +520,10 @@ { "parentPluginId": "@kbn/securitysolution-utils", "id": "def-common.FILENAME_WILDCARD_WARNING", - "type": "Any", + "type": "string", "tags": [], "label": "FILENAME_WILDCARD_WARNING", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-utils/src/path_validations/index.ts", "deprecated": false, "trackAdoption": false, @@ -535,13 +532,10 @@ { "parentPluginId": "@kbn/securitysolution-utils", "id": "def-common.FILEPATH_WARNING", - "type": "Any", + "type": "string", "tags": [], "label": "FILEPATH_WARNING", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-securitysolution-utils/src/path_validations/index.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 02ac0326ecf46..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_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 | |-------------------|-----------|------------------------|-----------------| -| 31 | 2 | 29 | 0 | +| 31 | 0 | 29 | 0 | ## Common diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 00d06d7167c58..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-22 +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 117312c618eb2..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-22 +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 997208987faa0..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-22 +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 9d0df11cddae6..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-22 +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 e03c2405dfd5d..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-22 +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 882d99b3827ff..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-22 +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 214eb5a7a8fea..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-22 +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 38162575facf4..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-22 +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 1873bd99937e4..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-22 +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 e01c7c3dddf12..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-22 +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 d268386ea10e1..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-22 +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 1b543ea284d67..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-22 +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 f97ce72e19cce..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-22 +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 7a3c1a9788c2e..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-22 +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 28722cd4507a0..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-22 +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 e47391ae5c9ca..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-22 +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 be80dec7e9af1..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-22 +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 fe350e5336905..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-22 +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 1c60d453b8dc0..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-22 +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 967a3756931e1..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-22 +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 367a2528aef5a..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-22 +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 f4936db708142..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-22 +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 ce9b24781ec47..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-22 +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 a3004fe367380..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-22 +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 074af9654e40e..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-22 +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 72a984ad5d2ef..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-22 +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 7feb0d33a8f80..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-22 +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 bf6e1b87c0010..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-22 +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 053c0813f9021..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-22 +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 bd3cf24f2b0c7..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-22 +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 0695d0b95ec8d..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-22 +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 03f5d9c6e0789..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-22 +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 10d32091ca4c0..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-22 +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 125cf9b243a8b..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-22 +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 d994a7712e419..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-22 +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 7dc7e0f52a3f6..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-22 +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 0f6c48885d13c..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-22 +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 849efcad0f435..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-22 +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 7a7b927fd6988..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-22 +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 255161288d28c..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-22 +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 39b4e5aec744b..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-22 +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 3acc41ae78f94..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-22 +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 a402d2bab9080..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-22 +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 1e775df2fb59a..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-22 +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 f128798cd26e0..02eec6e3a39cb 100644 --- a/api_docs/kbn_slo_schema.devdocs.json +++ b/api_docs/kbn_slo_schema.devdocs.json @@ -551,7 +551,7 @@ "label": "CreateSLOInput", "description": [], "signature": [ - "{ 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; } & { id?: string | undefined; settings?: { syncDelay?: string | undefined; frequency?: string | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }" + "{ 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; } & { id?: string | undefined; settings?: { syncDelay?: string | undefined; frequency?: string | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -566,7 +566,7 @@ "label": "CreateSLOParams", "description": [], "signature": [ - "{ 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: ", + "{ 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", @@ -688,6 +688,25 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.FindSloDefinitionsResponse", + "type": "Type", + "tags": [ + "private" + ], + "label": "FindSloDefinitionsResponse", + "description": [ + "\nThe response type for /internal/observability/slo/_definitions\n" + ], + "signature": [ + "({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; })[]" + ], + "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.FindSLOParams", @@ -711,7 +730,7 @@ "label": "FindSLOResponse", "description": [], "signature": [ - "{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }" + "{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -741,7 +760,7 @@ "label": "GetPreviewDataParams", "description": [], "signature": [ - "{ 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; }" + "{ 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; }; }; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -816,7 +835,7 @@ "label": "GetSLOResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -831,7 +850,7 @@ "label": "HistogramIndicator", "description": [], "signature": [ - "{ type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }" + "{ 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; }; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -861,7 +880,7 @@ "label": "Indicator", "description": [], "signature": [ - "{ 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }" + "{ 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; }; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -891,7 +910,7 @@ "label": "KQLCustomIndicator", "description": [], "signature": [ - "{ type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; }" + "{ type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -921,7 +940,7 @@ "label": "MetricCustomIndicator", "description": [], "signature": [ - "{ type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; }" + "{ 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; }; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -936,7 +955,7 @@ "label": "SLOResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -951,7 +970,7 @@ "label": "SLOWithSummaryResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -1050,7 +1069,7 @@ "label": "UpdateSLOInput", "description": [], "signature": [ - "{ name?: string | undefined; description?: string | undefined; 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; } | undefined; timeWindow?: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; } | undefined; budgetingMethod?: \"occurrences\" | \"timeslices\" | undefined; objective?: ({ target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }) | undefined; settings?: { syncDelay?: string | undefined; frequency?: string | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }" + "{ name?: string | undefined; description?: string | undefined; 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; }; } | undefined; timeWindow?: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; } | undefined; budgetingMethod?: \"occurrences\" | \"timeslices\" | undefined; objective?: ({ target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }) | undefined; settings?: { syncDelay?: string | undefined; frequency?: string | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -1065,7 +1084,7 @@ "label": "UpdateSLOParams", "description": [], "signature": [ - "{ name?: string | undefined; description?: string | undefined; 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; } | undefined; timeWindow?: { duration: ", + "{ name?: string | undefined; description?: string | undefined; 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; }; } | undefined; timeWindow?: { duration: ", { "pluginId": "@kbn/slo-schema", "scope": "common", @@ -1120,7 +1139,7 @@ "label": "UpdateSLOResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -1758,27 +1777,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -1821,18 +1844,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -1893,7 +1920,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -2370,6 +2401,396 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.findSloDefinitionsParamsSchema", + "type": "Object", + "tags": [ + "private" + ], + "label": "findSloDefinitionsParamsSchema", + "description": [ + "\nThe query params schema for /internal/observability/slo/_definitions\n" + ], + "signature": [ + "TypeC", + "<{ query: ", + "TypeC", + "<{ search: ", + "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.findSloDefinitionsResponseSchema", + "type": "Object", + "tags": [ + "private" + ], + "label": "findSloDefinitionsResponseSchema", + "description": [ + "\nThe response schema for /internal/observability/slo/_definitions\n" + ], + "signature": [ + "ArrayC", + "<", + "IntersectionC", + "<[", + "TypeC", + "<{ id: ", + "StringC", + "; name: ", + "StringC", + "; description: ", + "StringC", + "; indicator: ", + "UnionC", + "<[", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.apm.transactionDuration\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ environment: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; service: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; transactionType: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; transactionName: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; threshold: ", + "NumberC", + "; index: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.apm.transactionErrorRate\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ environment: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; service: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; transactionType: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; transactionName: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; index: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ index: ", + "StringC", + "; good: ", + "StringC", + "; total: ", + "StringC", + "; timestampField: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ index: ", + "StringC", + "; good: ", + "TypeC", + "<{ metrics: ", + "ArrayC", + "<", + "IntersectionC", + "<[", + "TypeC", + "<{ name: ", + "StringC", + "; aggregation: ", + "KeyofC", + "<{ sum: boolean; }>; field: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>>; equation: ", + "StringC", + "; }>; total: ", + "TypeC", + "<{ metrics: ", + "ArrayC", + "<", + "IntersectionC", + "<[", + "TypeC", + "<{ name: ", + "StringC", + "; aggregation: ", + "KeyofC", + "<{ sum: boolean; }>; field: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>>; equation: ", + "StringC", + "; }>; timestampField: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ index: ", + "StringC", + "; timestampField: ", + "StringC", + "; good: ", + "UnionC", + "<[", + "IntersectionC", + "<[", + "TypeC", + "<{ field: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"value_count\">; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ field: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"range\">; from: ", + "NumberC", + "; to: ", + "NumberC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>]>; total: ", + "UnionC", + "<[", + "IntersectionC", + "<[", + "TypeC", + "<{ field: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"value_count\">; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ field: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"range\">; from: ", + "NumberC", + "; to: ", + "NumberC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", + "UnionC", + "<[", + "TypeC", + "<{ duration: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; type: ", + "LiteralC", + "<\"rolling\">; }>, ", + "TypeC", + "<{ duration: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; type: ", + "LiteralC", + "<\"calendarAligned\">; }>]>; budgetingMethod: ", + "UnionC", + "<[", + "LiteralC", + "<\"occurrences\">, ", + "LiteralC", + "<\"timeslices\">]>; objective: ", + "IntersectionC", + "<[", + "TypeC", + "<{ target: ", + "NumberC", + "; }>, ", + "PartialC", + "<{ timesliceTarget: ", + "NumberC", + "; timesliceWindow: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; }>]>; revision: ", + "NumberC", + "; settings: ", + "TypeC", + "<{ syncDelay: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; frequency: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; }>; enabled: ", + "BooleanC", + "; tags: ", + "ArrayC", + "<", + "StringC", + ">; groupBy: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; createdAt: ", + "Type", + "; updatedAt: ", + "Type", + "; }>, ", + "PartialC", + "<{ instanceId: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; }>]>>" + ], + "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/slo-schema", "id": "def-common.findSLOParamsSchema", @@ -2524,27 +2945,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -2587,18 +3012,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -2659,7 +3088,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -2912,27 +3345,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -2975,18 +3412,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -3047,7 +3488,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; }>; }>" + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; }>; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -3146,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", @@ -3344,27 +3769,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -3407,18 +3836,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -3479,7 +3912,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -3628,13 +4065,13 @@ "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -3695,7 +4132,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>" + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/schema/indicators.ts", "deprecated": false, @@ -3880,27 +4321,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -3943,18 +4388,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -4015,7 +4464,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>" + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>" ], "path": "x-pack/packages/kbn-slo-schema/src/schema/indicators.ts", "deprecated": false, @@ -4076,18 +4529,22 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>" + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/schema/indicators.ts", "deprecated": false, @@ -4142,11 +4599,11 @@ "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -4189,7 +4646,11 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>" + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/schema/indicators.ts", "deprecated": false, @@ -4515,27 +4976,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -4578,18 +5043,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -4650,7 +5119,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -4861,27 +5334,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -4924,18 +5401,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -4996,7 +5477,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -5203,27 +5688,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -5266,18 +5755,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -5338,7 +5831,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -5577,27 +6074,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -5640,18 +6141,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -5712,7 +6217,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -6315,27 +6824,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -6378,18 +6891,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -6450,7 +6967,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -6647,27 +7168,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -6710,18 +7235,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -6782,7 +7311,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 74e22890aea41..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 130 | 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 7ccc711ffec51..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-22 +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 9419624fe1b64..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-22 +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 01f2a3fe722e8..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-22 +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 509adfada930c..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-22 +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 bed75cebc4ebd..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-22 +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 eb21d28bcccd2..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-22 +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 2996916ce82dd..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-22 +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 1a0dc4f113f00..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-22 +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 37e19b6610af3..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-22 +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 c0e891396dce2..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-22 +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 96cca4b893cde..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-22 +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 cea81124526bb..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-22 +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.devdocs.json b/api_docs/kbn_ui_actions_browser.devdocs.json index 3613ab2507d1b..7a589d952a59a 100644 --- a/api_docs/kbn_ui_actions_browser.devdocs.json +++ b/api_docs/kbn_ui_actions_browser.devdocs.json @@ -641,13 +641,10 @@ { "parentPluginId": "@kbn/ui-actions-browser", "id": "def-common.rowClickTrigger.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-ui-actions-browser/src/triggers/row_click_trigger.ts", "deprecated": false, "trackAdoption": false @@ -655,13 +652,10 @@ { "parentPluginId": "@kbn/ui-actions-browser", "id": "def-common.rowClickTrigger.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-ui-actions-browser/src/triggers/row_click_trigger.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/kbn_ui_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index 28534552bf03d..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.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 | |-------------------|-----------|------------------------|-----------------| -| 49 | 2 | 35 | 0 | +| 49 | 0 | 35 | 0 | ## Common diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 3f7ee1de09d29..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-22 +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 e9f6d4a2aba64..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-22 +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 210d3430aa7a7..dddaeb04aa725 100644 --- a/api_docs/kbn_unified_field_list.devdocs.json +++ b/api_docs/kbn_unified_field_list.devdocs.json @@ -771,7 +771,7 @@ "\nReturns a user-friendly description of a field type" ], "signature": [ - "(type: string | undefined) => any" + "(type: string | undefined) => string" ], "path": "packages/kbn-unified-field-list/src/utils/field_types/get_field_type_description.ts", "deprecated": false, @@ -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) => any" - ], - "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 4a8e1d97e4b0e..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-22 +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 06d856fa83997..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-22 +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 d8fa7b77fac93..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-22 +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 3fd1084822dd1..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-22 +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 a076dcf2fca9d..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-22 +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 f77c074ac5f0a..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-22 +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 7e23711dc6b80..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-22 +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.devdocs.json b/api_docs/kbn_visualization_ui_components.devdocs.json index 8fee65d445c51..0b9da0c5161ea 100644 --- a/api_docs/kbn_visualization_ui_components.devdocs.json +++ b/api_docs/kbn_visualization_ui_components.devdocs.json @@ -2533,13 +2533,10 @@ { "parentPluginId": "@kbn/visualization-ui-components", "id": "def-public.emptyTitleText", - "type": "Any", + "type": "string", "tags": [], "label": "emptyTitleText", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-visualization-ui-components/components/dimension_buttons/constants.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index cadd7cb792618..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 155 | 1 | 151 | 3 | +| 155 | 0 | 151 | 3 | ## Client diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 6cfb71c12eb5f..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-22 +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 200fc59a040b5..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-22 +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 8467d7714fea5..3133e29cbacf4 100644 --- a/api_docs/kibana_react.devdocs.json +++ b/api_docs/kibana_react.devdocs.json @@ -776,6 +776,126 @@ "plugin": "spaces", "path": "x-pack/plugins/spaces/public/space_selector/space_selector.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": "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" @@ -788,6 +908,22 @@ "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", "path": "x-pack/plugins/serverless/public/plugin.tsx" @@ -1068,126 +1204,6 @@ "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": "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": "alerting", "path": "x-pack/plugins/alerting/public/application/maintenance_windows.tsx" @@ -1202,99 +1218,39 @@ }, { "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/public/application/app.tsx" - }, - { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/public/application/app.tsx" - }, - { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/public/application/app.tsx" - }, - { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/public/application/connectors_app.tsx" - }, - { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/public/application/connectors_app.tsx" - }, - { - "plugin": "triggersActionsUi", - "path": "x-pack/plugins/triggers_actions_ui/public/application/connectors_app.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/application.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/application.tsx" - }, - { - "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" + "path": "x-pack/plugins/triggers_actions_ui/public/application/app.tsx" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/integrations/app.tsx" + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/application/app.tsx" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/integrations/app.tsx" + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/application/app.tsx" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/application/connectors_app.tsx" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/application/connectors_app.tsx" }, { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/application/connectors_app.tsx" }, { - "plugin": "observability", - "path": "x-pack/plugins/observability/public/application/index.tsx" + "plugin": "cases", + "path": "x-pack/plugins/cases/public/application.tsx" }, { - "plugin": "observability", - "path": "x-pack/plugins/observability/public/application/index.tsx" + "plugin": "cases", + "path": "x-pack/plugins/cases/public/application.tsx" }, { - "plugin": "observability", - "path": "x-pack/plugins/observability/public/application/index.tsx" + "plugin": "cases", + "path": "x-pack/plugins/cases/public/application.tsx" }, { "plugin": "licenseManagement", @@ -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,30 +1856,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/app/app.tsx" }, - { - "plugin": "serverlessSearch", - "path": "x-pack/plugins/serverless_search/public/application/elasticsearch.tsx" - }, - { - "plugin": "serverlessSearch", - "path": "x-pack/plugins/serverless_search/public/application/elasticsearch.tsx" - }, - { - "plugin": "serverlessSearch", - "path": "x-pack/plugins/serverless_search/public/application/elasticsearch.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" @@ -2801,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" @@ -2885,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" @@ -3158,6 +3134,30 @@ "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" @@ -3166,6 +3166,26 @@ "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": "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": "dataViewEditor", "path": "src/plugins/data_view_editor/public/shared_imports.ts" @@ -3306,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" @@ -3334,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" @@ -3354,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" @@ -3386,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" @@ -3456,75 +3452,43 @@ }, { "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/visualizations/actions/add_to_existing_case.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/visualizations/actions/add_to_existing_case.tsx" - }, - { - "plugin": "@kbn/ml-date-picker", - "path": "x-pack/packages/ml/date_picker/src/hooks/use_date_picker_context.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/components/log_categorization/log_categorization_app_state.tsx" - }, - { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx" - }, - { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx" - }, - { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx" + "path": "x-pack/plugins/cases/public/components/visualizations/actions/add_to_existing_case.tsx" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx" + "plugin": "cases", + "path": "x-pack/plugins/cases/public/components/visualizations/actions/add_to_existing_case.tsx" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_app_state.tsx" + "plugin": "observabilityShared", + "path": "x-pack/plugins/observability_shared/public/components/header_menu/header_menu_portal.tsx" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_app_state.tsx" + "plugin": "observabilityShared", + "path": "x-pack/plugins/observability_shared/public/components/header_menu/header_menu_portal.tsx" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx" + "plugin": "telemetry", + "path": "src/plugins/telemetry/public/services/telemetry_notifications/render_opt_in_status_notice_banner.tsx" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx" + "plugin": "telemetry", + "path": "src/plugins/telemetry/public/services/telemetry_notifications/render_opt_in_status_notice_banner.tsx" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx" + "plugin": "advancedSettings", + "path": "src/plugins/advanced_settings/public/management_app/components/form/form.tsx" }, { - "plugin": "aiops", - "path": "x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx" + "plugin": "advancedSettings", + "path": "src/plugins/advanced_settings/public/management_app/components/form/form.tsx" }, { - "plugin": "observabilityShared", - "path": "x-pack/plugins/observability_shared/public/components/header_menu/header_menu_portal.tsx" + "plugin": "maps", + "path": "x-pack/plugins/maps/public/render_app.tsx" }, { - "plugin": "observabilityShared", - "path": "x-pack/plugins/observability_shared/public/components/header_menu/header_menu_portal.tsx" + "plugin": "maps", + "path": "x-pack/plugins/maps/public/render_app.tsx" }, { "plugin": "exploratoryView", @@ -3630,134 +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": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx" - }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/grid_embeddable.tsx" - }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx" - }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx" - }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/data_comparison/data_comparison_app_state.tsx" - }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/data_comparison/data_comparison_app_state.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/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/model_management/force_stop_dialog.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/model_management/force_stop_dialog.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/model_management/deployment_setup.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/model_management/deployment_setup.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/components/header_menu_portal/header_menu_portal.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/components/header_menu_portal/header_menu_portal.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/embeddables/common/resolve_job_selection.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/embeddables/job_creation/common/create_flyout.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/embeddables/job_creation/common/create_flyout.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_setup_flyout.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_setup_flyout.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/routing/use_active_route.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/routing/use_active_route.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/app.tsx" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/app.tsx" - }, { "plugin": "banners", "path": "x-pack/plugins/banners/public/plugin.tsx" @@ -3858,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" @@ -4090,130 +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/sections/create_transform/components/wizard/wizard.tsx" - }, - { - "plugin": "transform", - "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.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" @@ -6209,13 +5901,10 @@ { "parentPluginId": "kibanaReact", "id": "def-public.NO_DATA_RECOMMENDED", - "type": "Any", + "type": "string", "tags": [], "label": "NO_DATA_RECOMMENDED", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/kibana_react/public/page_template/no_data_page/no_data_page.tsx", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index e270cf7dd2574..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 186 | 1 | 147 | 5 | +| 186 | 0 | 147 | 5 | ## Client diff --git a/api_docs/kibana_utils.devdocs.json b/api_docs/kibana_utils.devdocs.json index a9f8c8bbeaced..a0c1a249a615d 100644 --- a/api_docs/kibana_utils.devdocs.json +++ b/api_docs/kibana_utils.devdocs.json @@ -9243,7 +9243,7 @@ "section": "def-common.Serializable", "text": "Serializable" }, - ">) => S" + ">, loose: boolean | undefined) => S" ], "path": "src/plugins/kibana_utils/common/persistable_state/migrate_to_latest.ts", "deprecated": false, @@ -9299,6 +9299,21 @@ "deprecated": false, "trackAdoption": false, "isRequired": true + }, + { + "parentPluginId": "kibanaUtils", + "id": "def-common.migrateToLatest.$3", + "type": "CompoundType", + "tags": [], + "label": "loose", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/kibana_utils/common/persistable_state/migrate_to_latest.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false } ], "returnComment": [], @@ -10079,7 +10094,7 @@ "tags": [], "label": "migrations", "description": [ - "\nA list of migration functions, which migrate the persistable state\nserializable object to the next version. Migration functions should are\nkeyed by the Kibana version using semver, where the version indicates to\nwhich version the state will be migrated to." + "\nA list of migration functions, which migrate the persistable state\nserializable object to the next version. Migration functions should be\nkeyed using semver, where the version indicates which version the state\nwill be migrated to." ], "signature": [ { diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 653fc0d1ece0b..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/kib | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 609 | 3 | 416 | 9 | +| 610 | 3 | 417 | 9 | ## Client diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 31d95dd7b8306..60a832a0977dc 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,14 +8,14 @@ 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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; -Contact [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/teams/sec-cloudnative-integrations) for questions regarding this plugin. +Contact [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index b704f6bfd49f0..331601a978bd5 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -8459,7 +8459,7 @@ }, "<", "YDomainRange", - " | undefined>; hide?: boolean | undefined; showOverlappingTicks?: boolean | undefined; showOverlappingLabels?: boolean | undefined; timeAxisLayerCount?: number | undefined; integersOnly?: boolean | undefined; tickFormat?: \"ignore\" | undefined; labelFormat?: \"ignore\" | undefined; showDuplicatedTicks?: boolean | undefined; }>> & Partial; hide?: boolean | undefined; showOverlappingTicks?: boolean | undefined; showOverlappingLabels?: boolean | undefined; timeAxisLayerCount?: number | undefined; integersOnly?: boolean | undefined; tickFormat?: \"ignore\" | undefined; labelFormat?: \"ignore\" | undefined; showDuplicatedTicks?: boolean | undefined; }>> & Partial | LensAttributes; overrides?: Partial | LensAttributes; overrides?: Partial string" @@ -1829,17 +1829,17 @@ "trackAdoption": false, "children": [], "returnComment": [ - "The list index name" + "The list data stream/index name" ] }, { "parentPluginId": "lists", - "id": "def-server.ListClient.getListItemIndex", + "id": "def-server.ListClient.getListItemName", "type": "Function", "tags": [], - "label": "getListItemIndex", + "label": "getListItemName", "description": [ - "\nReturns the list item index name" + "\nReturns the list item data stream or index name" ], "signature": [ "() => string" @@ -1849,7 +1849,7 @@ "trackAdoption": false, "children": [], "returnComment": [ - "The list item index name" + "The list item data stream/index name" ] }, { @@ -1864,7 +1864,7 @@ "signature": [ "({ id }: ", "GetListOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; } | null>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -1902,7 +1902,7 @@ "signature": [ "({ id, deserializer, immutable, serializer, name, description, type, meta, version, }: ", "CreateListOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -1940,7 +1940,7 @@ "signature": [ "({ id, deserializer, serializer, name, description, immutable, type, meta, version, }: ", "CreateListIfItDoesNotExistOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -1986,6 +1986,26 @@ "True if the list index exists, otherwise false" ] }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.getListDataStreamExists", + "type": "Function", + "tags": [], + "label": "getListDataStreamExists", + "description": [ + "\nTrue if the list data stream exists, otherwise false" + ], + "signature": [ + "() => Promise" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "True if the list data stream exists, otherwise false" + ] + }, { "parentPluginId": "lists", "id": "def-server.ListClient.getListItemIndexExists", @@ -2008,9 +2028,31 @@ }, { "parentPluginId": "lists", - "id": "def-server.ListClient.createListBootStrapIndex", + "id": "def-server.ListClient.getListItemDataStreamExists", "type": "Function", "tags": [], + "label": "getListItemDataStreamExists", + "description": [ + "\nTrue if the list item data stream exists, otherwise false" + ], + "signature": [ + "() => Promise" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "True if the list item data stream exists, otherwise false" + ] + }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.createListBootStrapIndex", + "type": "Function", + "tags": [ + "deprecated" + ], "label": "createListBootStrapIndex", "description": [ "\nCreates the list boot strap index for ILM policies." @@ -2019,8 +2061,9 @@ "() => Promise" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", - "deprecated": false, + "deprecated": true, "trackAdoption": false, + "references": [], "children": [], "returnComment": [ "The contents of the bootstrap response from Elasticsearch" @@ -2028,9 +2071,67 @@ }, { "parentPluginId": "lists", - "id": "def-server.ListClient.createListItemBootStrapIndex", + "id": "def-server.ListClient.createListDataStream", + "type": "Function", + "tags": [], + "label": "createListDataStream", + "description": [ + "\nCreates list data stream" + ], + "signature": [ + "() => Promise" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "The contents of the create data stream from Elasticsearch" + ] + }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.migrateListIndexToDataStream", + "type": "Function", + "tags": [], + "label": "migrateListIndexToDataStream", + "description": [ + "\nupdate list index mappings with @timestamp and migrates it to data stream" + ], + "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.migrateListItemIndexToDataStream", "type": "Function", "tags": [], + "label": "migrateListItemIndexToDataStream", + "description": [ + "\nupdate list items index mappings with @timestamp and migrates it to data stream" + ], + "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.createListItemBootStrapIndex", + "type": "Function", + "tags": [ + "deprecated" + ], "label": "createListItemBootStrapIndex", "description": [ "\nCreates the list item boot strap index for ILM policies." @@ -2039,13 +2140,34 @@ "() => Promise" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", - "deprecated": false, + "deprecated": true, "trackAdoption": false, + "references": [], "children": [], "returnComment": [ "The contents of the bootstrap response from Elasticsearch" ] }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.createListItemDataStream", + "type": "Function", + "tags": [], + "label": "createListItemDataStream", + "description": [ + "\nCreates list item data stream" + ], + "signature": [ + "() => Promise" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "The contents of the create data stream from Elasticsearch" + ] + }, { "parentPluginId": "lists", "id": "def-server.ListClient.getListPolicyExists", @@ -2250,7 +2372,9 @@ "parentPluginId": "lists", "id": "def-server.ListClient.setListPolicy", "type": "Function", - "tags": [], + "tags": [ + "deprecated" + ], "label": "setListPolicy", "description": [ "\nSets the list policy" @@ -2259,8 +2383,9 @@ "() => Promise" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", - "deprecated": false, + "deprecated": true, "trackAdoption": false, + "references": [], "children": [], "returnComment": [ "The contents of the list policy set" @@ -2270,7 +2395,9 @@ "parentPluginId": "lists", "id": "def-server.ListClient.setListItemPolicy", "type": "Function", - "tags": [], + "tags": [ + "deprecated" + ], "label": "setListItemPolicy", "description": [ "\nSets the list item policy" @@ -2279,8 +2406,9 @@ "() => Promise" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", - "deprecated": false, + "deprecated": true, "trackAdoption": false, + "references": [], "children": [], "returnComment": [ "The contents of the list policy set" @@ -2326,6 +2454,46 @@ "True if the list item index was deleted, otherwise false" ] }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.deleteListDataStream", + "type": "Function", + "tags": [], + "label": "deleteListDataStream", + "description": [ + "\nDeletes the list data stream" + ], + "signature": [ + "() => Promise" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "True if the list index was deleted, otherwise false" + ] + }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.deleteListItemDataStream", + "type": "Function", + "tags": [], + "label": "deleteListItemDataStream", + "description": [ + "\nDeletes the list item data stream" + ], + "signature": [ + "() => Promise" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "True if the list index was deleted, otherwise false" + ] + }, { "parentPluginId": "lists", "id": "def-server.ListClient.deleteListPolicy", @@ -2426,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", @@ -2446,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", @@ -2458,7 +2662,7 @@ "signature": [ "({ id }: ", "DeleteListItemOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; } | null>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2496,7 +2700,7 @@ "signature": [ "({ listId, value, type, }: ", "DeleteListItemByValueOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2534,7 +2738,7 @@ "signature": [ "({ id }: ", "DeleteListOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; } | null>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2608,7 +2812,7 @@ "signature": [ "({ deserializer, serializer, type, listId, stream, meta, version, }: ", "ImportListItemsToStreamOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; } | null>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2644,7 +2848,7 @@ "signature": [ "({ listId, value, type, }: ", "GetListItemByValueOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2682,7 +2886,7 @@ "signature": [ "({ id, deserializer, serializer, listId, value, type, meta, }: ", "CreateListItemOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; } | null>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2718,7 +2922,7 @@ "signature": [ "({ _version, id, value, meta, }: ", "UpdateListItemOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; } | null>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2742,6 +2946,42 @@ ], "returnComment": [] }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.patchListItem", + "type": "Function", + "tags": [], + "label": "patchListItem", + "description": [ + "\nPatches a list item's value given the id of the list item.\nSee {@link https://www.elastic.co/guide/en/elasticsearch/reference/current/optimistic-concurrency-control.html}\nfor more information around optimistic concurrency control." + ], + "signature": [ + "({ _version, id, value, meta, }: ", + "UpdateListItemOptions", + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; } | null>" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lists", + "id": "def-server.ListClient.patchListItem.$1", + "type": "Object", + "tags": [], + "label": "{\n _version,\n id,\n value,\n meta,\n }", + "description": [], + "signature": [ + "UpdateListItemOptions" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "lists", "id": "def-server.ListClient.updateList", @@ -2754,7 +2994,7 @@ "signature": [ "({ _version, id, name, description, meta, version, }: ", "UpdateListOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; } | null>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2778,6 +3018,42 @@ ], "returnComment": [] }, + { + "parentPluginId": "lists", + "id": "def-server.ListClient.patchList", + "type": "Function", + "tags": [], + "label": "patchList", + "description": [ + "\nPatches a list container's value given the id of the list." + ], + "signature": [ + "({ _version, id, name, description, meta, version, }: ", + "UpdateListOptions", + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; } | null>" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lists", + "id": "def-server.ListClient.patchList.$1", + "type": "Object", + "tags": [], + "label": "{\n _version,\n id,\n name,\n description,\n meta,\n version,\n }", + "description": [], + "signature": [ + "UpdateListOptions" + ], + "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "lists", "id": "def-server.ListClient.getListItem", @@ -2790,7 +3066,7 @@ "signature": [ "({ id }: ", "GetListItemOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; } | null>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2828,7 +3104,7 @@ "signature": [ "({ type, listId, value, }: ", "GetListItemsByValueOptions", - ") => Promise<{ _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]>" + ") => Promise<{ _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2866,7 +3142,7 @@ "signature": [ "({ type, listId, value, }: ", "SearchListItemByValuesOptions", - ") => Promise<{ items: { _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; value: unknown; }[]>" + ") => Promise<{ items: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; value: unknown; }[]>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2904,7 +3180,7 @@ "signature": [ "({ filter, currentIndexPosition, perPage, page, sortField, sortOrder, searchAfter, runtimeMappings, }: ", "FindListOptions", - ") => Promise<{ cursor: string; data: { _version: string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; page: number; per_page: number; total: number; }>" + ") => Promise<{ cursor: string; data: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; description: string; deserializer: string | undefined; id: string; immutable: boolean; meta: object | undefined; name: string; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; version: number; }[]; page: number; per_page: number; total: number; }>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2942,7 +3218,7 @@ "signature": [ "({ listId, filter, currentIndexPosition, perPage, page, runtimeMappings, sortField, sortOrder, searchAfter, }: ", "FindListItemOptions", - ") => Promise<{ cursor: string; data: { _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; page: number; per_page: number; total: number; } | null>" + ") => Promise<{ cursor: string; data: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; page: number; per_page: number; total: number; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, @@ -2978,7 +3254,7 @@ "signature": [ "({ listId, filter, sortField, sortOrder, }: ", "FindAllListItemsOptions", - ") => Promise<{ data: { _version: string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; total: number; } | null>" + ") => Promise<{ data: { _version: string | undefined; '@timestamp': string | undefined; created_at: string; created_by: string; deserializer: string | undefined; id: string; list_id: string; meta: object | undefined; serializer: string | undefined; tie_breaker_id: string; type: \"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"binary\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"integer\" | \"long\" | \"short\" | \"byte\" | \"float\" | \"half_float\" | \"double\" | \"integer_range\" | \"float_range\" | \"long_range\" | \"double_range\" | \"date_range\" | \"ip_range\" | \"shape\"; updated_at: string; updated_by: string; value: string; }[]; total: number; } | null>" ], "path": "x-pack/plugins/lists/server/services/lists/list_client.ts", "deprecated": false, diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index d9930040ed046..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 210 | 0 | 94 | 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 d8fbe858d753d..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-22 +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 18ecbda2ce64c..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-22 +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 f3f28a8aef7f1..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-22 +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 b6ff9efaa8dc5..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-22 +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 d29cc9e62530d..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-22 +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 acc2ea7d932f1..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-22 +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 9dacaef9bce8a..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-22 +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 ddd03909ca079..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-22 +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 7fcac650a7ba0..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-22 +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 51f2c8ba425ea..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-22 +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 2b615018f7ead..e910e74323d61 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -498,7 +498,7 @@ "label": "formatAlertEvaluationValue", "description": [], "signature": [ - "(ruleTypeId?: string | undefined, evaluationValue?: number | undefined) => any" + "(ruleTypeId?: string | undefined, evaluationValue?: number | undefined) => string | number" ], "path": "x-pack/plugins/observability/public/utils/format_alert_evaluation_value.ts", "deprecated": false, @@ -3207,7 +3207,7 @@ "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", - ", denominator: number | undefined, fallbackResult?: any) => any; }; }) => { reason: string; link?: string | undefined; }" + ", denominator: number | undefined, fallbackResult?: string) => string; }; }) => { reason: string; link?: string | undefined; }" ], "path": "x-pack/plugins/observability/public/rules/create_observability_rule_type_registry.ts", "deprecated": false, @@ -3226,7 +3226,7 @@ "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", - ", denominator: number | undefined, fallbackResult?: any) => any; }; }" + ", denominator: number | undefined, fallbackResult?: string) => string; }; }" ], "path": "x-pack/plugins/observability/public/rules/create_observability_rule_type_registry.ts", "deprecated": false, @@ -4220,7 +4220,7 @@ "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", - ", denominator: number | undefined, fallbackResult?: any) => any; }; }) => { reason: string; link?: string | undefined; }" + ", denominator: number | undefined, fallbackResult?: string) => string; }; }) => { reason: string; link?: string | undefined; }" ], "path": "x-pack/plugins/observability/public/rules/create_observability_rule_type_registry.ts", "deprecated": false, @@ -4239,7 +4239,7 @@ "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", - ", denominator: number | undefined, fallbackResult?: any) => any; }; }" + ", denominator: number | undefined, fallbackResult?: string) => string; }; }" ], "path": "x-pack/plugins/observability/public/rules/create_observability_rule_type_registry.ts", "deprecated": false, @@ -4470,7 +4470,7 @@ "text": "LocatorPublic" }, "<", - "RulesLocatorParams", + "RulesParams", ">; ruleDetailsLocator: ", { "pluginId": "share", @@ -7898,7 +7898,7 @@ "label": "config", "description": [], "signature": [ - "{ readonly enabled: boolean; readonly annotations: Readonly<{} & { index: string; enabled: boolean; }>; readonly unsafe: Readonly<{} & { alertDetails: Readonly<{} & { uptime: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; observability: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; }>; thresholdRule: Readonly<{} & { enabled: boolean; }>; }>; readonly thresholdRule: Readonly<{} & { groupByPageSize: number; }>; readonly compositeSlo: Readonly<{} & { enabled: boolean; }>; }" + "{ readonly enabled: boolean; readonly unsafe: Readonly<{} & { alertDetails: Readonly<{} & { uptime: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; observability: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; }>; thresholdRule: Readonly<{} & { enabled: boolean; }>; }>; readonly annotations: Readonly<{} & { index: string; enabled: boolean; }>; readonly thresholdRule: Readonly<{} & { groupByPageSize: number; }>; readonly compositeSlo: Readonly<{} & { enabled: boolean; }>; }" ], "path": "x-pack/plugins/observability/server/routes/types.ts", "deprecated": false, @@ -8410,27 +8410,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -8473,18 +8477,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -8545,7 +8553,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; }>; }> | undefined; handler: ({}: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; }>; }> | undefined; handler: ({}: ", { "pluginId": "observability", "scope": "server", @@ -8553,7 +8565,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { body: { 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; }; }; }) => Promise<{ date: string; sliValue: number; }[]>; } & ", + " & { params: { body: { 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; }; }; }; }; }) => Promise<{ date: string; sliValue: number; }[]>; } & ", { "pluginId": "observability", "scope": "server", @@ -8615,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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; 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", @@ -8691,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", @@ -8800,27 +8746,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -8863,18 +8813,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -8935,7 +8889,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -9031,7 +8989,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { path: { id: string; }; body: { name?: string | undefined; description?: string | undefined; 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; } | undefined; timeWindow?: { duration: ", + " & { params: { path: { id: string; }; body: { name?: string | undefined; description?: string | undefined; 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; }; } | undefined; timeWindow?: { duration: ", { "pluginId": "@kbn/slo-schema", "scope": "common", @@ -9071,7 +9029,7 @@ "section": "def-common.Duration", "text": "Duration" }, - " | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }; }; }) => Promise<{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }>; } & ", + " | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }; }; }) => Promise<{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -9105,7 +9063,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { path: { id: string; }; } & { query?: { instanceId?: string | undefined; } | undefined; }; }) => Promise<{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }>; } & ", + " & { params: { path: { id: string; }; } & { query?: { instanceId?: string | undefined; } | undefined; }; }) => Promise<{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -9147,7 +9105,29 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params?: { query?: { kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; } | undefined; } | undefined; }) => Promise<{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }>; } & ", + " & { params?: { query?: { kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; } | undefined; } | undefined; }) => Promise<{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }>; } & ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteCreateOptions", + "text": "ObservabilityRouteCreateOptions" + }, + "; \"GET /internal/observability/slos/_definitions\": { endpoint: \"GET /internal/observability/slos/_definitions\"; params?: ", + "TypeC", + "<{ query: ", + "TypeC", + "<{ search: ", + "StringC", + "; }>; }> | undefined; handler: ({}: ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteHandlerResources", + "text": "ObservabilityRouteHandlerResources" + }, + " & { params: { query: { search: string; }; }; }) => Promise<({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; })[]>; } & ", { "pluginId": "observability", "scope": "server", @@ -9348,27 +9328,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -9411,18 +9395,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -9483,7 +9471,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -9583,7 +9575,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { body: { 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: ", + " & { params: { body: { 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", @@ -9674,7 +9666,7 @@ "label": "ObservabilityConfig", "description": [], "signature": [ - "{ readonly enabled: boolean; readonly annotations: Readonly<{} & { index: string; enabled: boolean; }>; readonly unsafe: Readonly<{} & { alertDetails: Readonly<{} & { uptime: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; observability: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; }>; thresholdRule: Readonly<{} & { enabled: boolean; }>; }>; readonly thresholdRule: Readonly<{} & { groupByPageSize: number; }>; readonly compositeSlo: Readonly<{} & { enabled: boolean; }>; }" + "{ readonly enabled: boolean; readonly unsafe: Readonly<{} & { alertDetails: Readonly<{} & { uptime: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; observability: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; }>; thresholdRule: Readonly<{} & { enabled: boolean; }>; }>; readonly annotations: Readonly<{} & { index: string; enabled: boolean; }>; readonly thresholdRule: Readonly<{} & { groupByPageSize: number; }>; readonly compositeSlo: Readonly<{} & { enabled: boolean; }>; }" ], "path": "x-pack/plugins/observability/server/index.ts", "deprecated": false, @@ -10124,27 +10116,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -10187,18 +10183,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -10259,7 +10259,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; }>; }> | undefined; handler: ({}: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; }>; }> | undefined; handler: ({}: ", { "pluginId": "observability", "scope": "server", @@ -10267,7 +10271,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { body: { 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; }; }; }) => Promise<{ date: string; sliValue: number; }[]>; } & ", + " & { params: { body: { 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; }; }; }; }; }) => Promise<{ date: string; sliValue: number; }[]>; } & ", { "pluginId": "observability", "scope": "server", @@ -10329,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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; 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", @@ -10405,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", @@ -10514,27 +10452,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -10577,18 +10519,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -10649,7 +10595,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -10745,7 +10695,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { path: { id: string; }; body: { name?: string | undefined; description?: string | undefined; 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; } | undefined; timeWindow?: { duration: ", + " & { params: { path: { id: string; }; body: { name?: string | undefined; description?: string | undefined; 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; }; } | undefined; timeWindow?: { duration: ", { "pluginId": "@kbn/slo-schema", "scope": "common", @@ -10785,7 +10735,7 @@ "section": "def-common.Duration", "text": "Duration" }, - " | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }; }; }) => Promise<{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }>; } & ", + " | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }; }; }) => Promise<{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -10819,7 +10769,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { path: { id: string; }; } & { query?: { instanceId?: string | undefined; } | undefined; }; }) => Promise<{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }>; } & ", + " & { params: { path: { id: string; }; } & { query?: { instanceId?: string | undefined; } | undefined; }; }) => Promise<{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -10861,7 +10811,29 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params?: { query?: { kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; } | undefined; } | undefined; }) => Promise<{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }>; } & ", + " & { params?: { query?: { kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; } | undefined; } | undefined; }) => Promise<{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }>; } & ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteCreateOptions", + "text": "ObservabilityRouteCreateOptions" + }, + "; \"GET /internal/observability/slos/_definitions\": { endpoint: \"GET /internal/observability/slos/_definitions\"; params?: ", + "TypeC", + "<{ query: ", + "TypeC", + "<{ search: ", + "StringC", + "; }>; }> | undefined; handler: ({}: ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteHandlerResources", + "text": "ObservabilityRouteHandlerResources" + }, + " & { params: { query: { search: string; }; }; }) => Promise<({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: ({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; })[]; 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: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; })[]>; } & ", { "pluginId": "observability", "scope": "server", @@ -11062,27 +11034,31 @@ "<{ type: ", "LiteralC", "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "StringC", "; total: ", "StringC", "; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", - "; filter: ", - "StringC", "; good: ", "TypeC", "<{ metrics: ", @@ -11125,18 +11101,22 @@ "StringC", "; }>; timestampField: ", "StringC", - "; }>; }>, ", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", "TypeC", "<{ type: ", "LiteralC", "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ index: ", "StringC", "; timestampField: ", "StringC", - "; filter: ", - "StringC", "; good: ", "UnionC", "<[", @@ -11197,7 +11177,11 @@ "PartialC", "<{ filter: ", "StringC", - "; }>]>]>; }>; }>]>; timeWindow: ", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", "UnionC", "<[", "TypeC", @@ -11297,7 +11281,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { body: { 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; filter: string; good: string; total: string; timestampField: string; }; } | { type: \"sli.metric.custom\"; params: { index: string; filter: 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; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; filter: 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; }); }; }; timeWindow: { duration: ", + " & { params: { body: { 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", @@ -11522,13 +11506,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableInspectEsQueries.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -11550,13 +11531,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableInspectEsQueries.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -11626,13 +11604,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.maxSuggestions.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -11651,13 +11626,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.maxSuggestions.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -11713,13 +11685,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableComparisonByDefault.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -11741,13 +11710,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableComparisonByDefault.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -11817,13 +11783,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.defaultApmServiceEnvironment.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -11831,13 +11794,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.defaultApmServiceEnvironment.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -11904,13 +11864,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmProgressiveLoading.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -11918,13 +11875,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmProgressiveLoading.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12041,13 +11995,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmProgressiveLoading.optionLabels.ProgressiveLoadingQuality.off", - "type": "Any", + "type": "string", "tags": [], "label": "[ProgressiveLoadingQuality.off]", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12055,13 +12006,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmProgressiveLoading.optionLabels.ProgressiveLoadingQuality.low", - "type": "Any", + "type": "string", "tags": [], "label": "[ProgressiveLoadingQuality.low]", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12069,13 +12017,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmProgressiveLoading.optionLabels.ProgressiveLoadingQuality.medium", - "type": "Any", + "type": "string", "tags": [], "label": "[ProgressiveLoadingQuality.medium]", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12083,13 +12028,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmProgressiveLoading.optionLabels.ProgressiveLoadingQuality.high", - "type": "Any", + "type": "string", "tags": [], "label": "[ProgressiveLoadingQuality.high]", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12140,13 +12082,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmServiceInventoryOptimizedSorting.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12154,13 +12093,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmServiceInventoryOptimizedSorting.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12272,13 +12208,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmServiceGroupMaxNumberOfServices.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12297,13 +12230,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmServiceGroupMaxNumberOfServices.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12359,13 +12289,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmTraceExplorerTab.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12373,13 +12300,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmTraceExplorerTab.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12491,13 +12415,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmLabsButton.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12505,13 +12426,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmLabsButton.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12609,13 +12527,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableInfrastructureHostsView.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12637,13 +12552,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableInfrastructureHostsView.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12699,13 +12611,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableAwsLambdaMetrics.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12713,13 +12622,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableAwsLambdaMetrics.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12831,13 +12737,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableAgentExplorerView.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12845,13 +12748,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableAgentExplorerView.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12949,13 +12849,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmAWSLambdaPriceFactor.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -12988,13 +12885,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmAWSLambdaPriceFactor.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13066,13 +12960,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmAWSLambdaRequestCostPerMillion.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13139,13 +13030,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmEnableServiceMetrics.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13167,13 +13055,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmEnableServiceMetrics.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13243,13 +13128,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmEnableContinuousRollups.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13271,13 +13153,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmEnableContinuousRollups.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13347,13 +13226,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableCriticalPath.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13361,13 +13237,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableCriticalPath.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13479,13 +13352,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.syntheticsThrottlingEnabled.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13507,13 +13377,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.syntheticsThrottlingEnabled.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13583,13 +13450,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableLegacyUptimeApp.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13611,13 +13475,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.enableLegacyUptimeApp.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13687,13 +13548,10 @@ { "parentPluginId": "observability", "id": "def-server.uiSettings.apmEnableProfilingIntegration.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, "trackAdoption": false @@ -13964,7 +13822,7 @@ "label": "asInteger", "description": [], "signature": [ - "(value: number | null | undefined) => any" + "(value: number | null | undefined) => string" ], "path": "x-pack/plugins/observability/common/utils/formatters/formatters.ts", "deprecated": false, @@ -13999,7 +13857,7 @@ "signature": [ "(numerator: ", "Maybe", - ", denominator: number | undefined, fallbackResult: any) => any" + ", denominator: number | undefined, fallbackResult: string) => string" ], "path": "x-pack/plugins/observability/common/utils/formatters/formatters.ts", "deprecated": false, @@ -14039,12 +13897,12 @@ { "parentPluginId": "observability", "id": "def-common.asPercent.$3", - "type": "Any", + "type": "string", "tags": [], "label": "fallbackResult", "description": [], "signature": [ - "any" + "string" ], "path": "x-pack/plugins/observability/common/utils/formatters/formatters.ts", "deprecated": false, @@ -14928,7 +14786,7 @@ "signature": [ "(numerator: ", "Maybe", - ", denominator: number | undefined, fallbackResult?: any) => any" + ", denominator: number | undefined, fallbackResult?: string) => string" ], "path": "x-pack/plugins/observability/common/utils/formatters/formatters.ts", "deprecated": false, @@ -14966,13 +14824,10 @@ { "parentPluginId": "observability", "id": "def-common.AsPercent.$3", - "type": "Any", + "type": "string", "tags": [], "label": "fallbackResult", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/observability/common/utils/formatters/formatters.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 078841d9806bb..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.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 | |-------------------|-----------|------------------------|-----------------| -| 541 | 46 | 532 | 16 | +| 541 | 2 | 532 | 16 | ## Client diff --git a/api_docs/observability_a_i_assistant.devdocs.json b/api_docs/observability_a_i_assistant.devdocs.json index a72e21c7dcd4e..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", @@ -486,8 +518,8 @@ "pluginId": "actions", "scope": "server", "docId": "kibActionsPluginApi", - "section": "def-server.FindActionResult", - "text": "FindActionResult" + "section": "def-server.FindConnectorResult", + "text": "FindConnectorResult" }, "[]>; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -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", @@ -819,8 +883,8 @@ "pluginId": "actions", "scope": "server", "docId": "kibActionsPluginApi", - "section": "def-server.FindActionResult", - "text": "FindActionResult" + "section": "def-server.FindConnectorResult", + "text": "FindConnectorResult" }, "[]>; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -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", @@ -1258,8 +1354,8 @@ "pluginId": "actions", "scope": "server", "docId": "kibActionsPluginApi", - "section": "def-server.FindActionResult", - "text": "FindActionResult" + "section": "def-server.FindConnectorResult", + "text": "FindConnectorResult" }, "[]>; } & ", "ObservabilityAIAssistantRouteCreateOptions", diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 09485143a3bc5..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-22 +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 d334d11abeb06..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-22 +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 895047172ccfb..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-22 +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 a55fb090cc886..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-22 +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 f03442577c57d..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,34 +15,35 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 664 | 554 | 40 | +| 674 | 564 | 39 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 72187 | 559 | 61676 | 1489 | +| 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) | - | 275 | 10 | 269 | 27 | +| | [@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. | 60 | 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 | 48 | 0 | 48 | 120 | +| | [@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) | - | 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/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 268 | 16 | 253 | 10 | +| | [@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 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | This plugin exists as a workaround for using `cloudChat` plugin in plugins which can't have a direct dependency on security plugin. | 5 | 0 | 5 | 0 | -| | [@elastic/platform-onboarding](https://github.com/orgs/elastic/teams/platform-onboarding) | Static migration page where self-managed users can see text/copy about migrating to Elastic Cloud | 8 | 1 | 8 | 1 | -| | [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/teams/sec-cloudnative-integrations) | Defend for containers (D4C) | 52 | 0 | 43 | 2 | +| | [@elastic/platform-onboarding](https://github.com/orgs/elastic/teams/platform-onboarding) | Static migration page where self-managed users can see text/copy about migrating to Elastic Cloud | 8 | 0 | 8 | 1 | +| | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | Defend for containers (D4C) | 52 | 0 | 43 | 2 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | Provides the necessary APIs to implement A/B testing scenarios, fetching the variations in configuration and reporting back metrics to track conversion rates of the experiments. | 12 | 0 | 0 | 0 | | cloudFullStory | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | When Kibana runs on Elastic Cloud, this plugin registers FullStory as a shipper for telemetry. | 0 | 0 | 0 | 0 | | cloudGainsight | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | When Kibana runs on Elastic Cloud, this plugin registers Gainsight as a shipper for telemetry. | 0 | 0 | 0 | 0 | @@ -54,30 +55,30 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | crossClusterReplication | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | | customBranding | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Enables customization of Kibana | 0 | 0 | 0 | 0 | | | [@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 | 100 | 0 | 98 | 9 | +| | [@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. | 3301 | 119 | 2575 | 27 | +| | [@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. | 1024 | 0 | 246 | 2 | +| | [@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/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 537 | 11 | 439 | 7 | +| | [@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 | -| | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | Adds dashboards for discovering and managing Enterprise Search products. | 10 | 0 | 10 | 0 | +| | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | Adds dashboards for discovering and managing Enterprise Search products. | 11 | 0 | 11 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 115 | 3 | 111 | 3 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | The Event Annotation service contains expressions for event annotations | 195 | 30 | 195 | 5 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | The Event Annotation service contains expressions for event annotations | 195 | 0 | 195 | 5 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 111 | 0 | 111 | 11 | | | [@elastic/uptime](https://github.com/orgs/elastic/teams/uptime) | - | 132 | 1 | 132 | 14 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'error' renderer to expressions | 17 | 0 | 15 | 2 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Gauge plugin adds a `gauge` renderer and function to the expression plugin. The renderer will display the `gauge` chart. | 59 | 0 | 59 | 2 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Heatmap plugin adds a `heatmap` renderer and function to the expression plugin. The renderer will display the `heatmap` chart. | 112 | 14 | 108 | 2 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Heatmap plugin adds a `heatmap` renderer and function to the expression plugin. The renderer will display the `heatmap` chart. | 112 | 0 | 108 | 2 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'image' function and renderer to expressions | 26 | 0 | 26 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds a `metric` renderer and function to the expression plugin. The renderer will display the `legacy metric` chart. | 51 | 0 | 51 | 2 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'metric' function and renderer to expressions | 32 | 0 | 27 | 0 | @@ -88,13 +89,13 @@ 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 | 74 | 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 | 26 | 253 | 3 | +| | [@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 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 239 | 0 | 24 | 9 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Simple UI for managing files in Kibana | 2 | 1 | 2 | 0 | -| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1188 | 3 | 1072 | 41 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Simple UI for managing files in Kibana | 2 | 0 | 2 | 0 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1189 | 3 | 1073 | 41 | | ftrApis | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 0 | 0 | 0 | 0 | @@ -102,25 +103,26 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | graph | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 0 | 0 | 0 | 0 | | grokdebugger | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | | | [@elastic/platform-onboarding](https://github.com/orgs/elastic/teams/platform-onboarding) | Guided onboarding framework | 58 | 0 | 57 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 145 | 0 | 106 | 0 | +| | [@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) | - | 185 | 0 | 180 | 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 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | - | 123 | 2 | 96 | 4 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides UI and APIs for the interactive setup mode. | 28 | 0 | 18 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 6 | 0 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 186 | 1 | 147 | 5 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 186 | 0 | 147 | 5 | | kibanaUsageCollection | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | -| | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 609 | 3 | 416 | 9 | -| | [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/teams/sec-cloudnative-integrations) | - | 5 | 0 | 5 | 1 | +| | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 610 | 3 | 417 | 9 | +| | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 5 | 0 | 5 | 1 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 616 | 0 | 519 | 61 | | | [@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) | - | 210 | 0 | 94 | 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 | @@ -131,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 | 46 | 532 | 16 | +| | [@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 | 8 | 164 | 11 | -| | [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) | - | 19 | 2 | 19 | 3 | +| | [@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) | - | 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 | @@ -155,13 +160,13 @@ 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) | - | 195 | 3 | 129 | 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 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Serverless customizations for observability. | 6 | 0 | 6 | 0 | | | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | Serverless customizations for search. | 6 | 0 | 6 | 0 | -| | [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/teams/sec-cloudnative-integrations) | - | 134 | 0 | 134 | 8 | +| | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 134 | 0 | 134 | 8 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Adds URL Service and sharing capabilities to Kibana | 119 | 0 | 60 | 10 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 22 | 1 | 22 | 1 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides the Spaces feature, which allows saved objects to be organized into meaningful categories. | 253 | 0 | 65 | 0 | @@ -173,16 +178,17 @@ 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 | | translations | [@elastic/kibana-localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 571 | 12 | 545 | 50 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Adds UI Actions service to Kibana | 145 | 2 | 103 | 9 | +| | [@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 | @@ -212,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 | @@ -240,7 +247,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 116 | 0 | 90 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 75 | 0 | 46 | 10 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 24 | 0 | 24 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 135 | 3 | 133 | 18 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 140 | 3 | 137 | 18 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 4 | 4 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 14 | 0 | 14 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 9 | 0 | 9 | 0 | @@ -258,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 | @@ -290,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 | @@ -351,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 | @@ -361,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 | @@ -371,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 | @@ -384,7 +391,7 @@ 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) | - | 11 | 0 | 11 | 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) | - | 55 | 1 | 49 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 61 | 1 | 54 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 15 | 0 | 14 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 4 | 0 | @@ -396,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 | @@ -413,30 +420,30 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 3 | 0 | 3 | 0 | | | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | - | 3 | 0 | 3 | 0 | | | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 4 | 0 | 4 | 0 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 7 | 1 | 7 | 0 | -| | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 7 | 1 | 7 | 0 | -| | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 7 | 1 | 7 | 0 | -| | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 7 | 1 | 7 | 0 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 7 | 0 | 7 | 0 | +| | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 7 | 0 | 7 | 0 | +| | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 7 | 0 | 7 | 0 | +| | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 7 | 0 | 7 | 0 | | | [@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/docs](https://github.com/orgs/elastic/teams/docs) | - | 72 | 0 | 72 | 2 | +| | [@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 | 2 | 5 | 0 | -| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 77 | 2 | 58 | 4 | -| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 4 | 0 | 4 | 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) | - | 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 | 1 | 39 | 0 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 65 | 1 | 65 | 1 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 39 | 0 | 39 | 0 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 65 | 0 | 65 | 1 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 36 | 0 | 14 | 3 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 20 | 0 | 16 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 0 | 0 | @@ -476,7 +483,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 37 | 0 | 0 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 152 | 1 | 0 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 141 | 0 | 5 | 0 | -| | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 52 | 0 | 4 | 0 | +| | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 47 | 0 | 0 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 11 | 0 | 0 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 36 | 4 | 8 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 11 | 0 | 0 | 0 | @@ -491,9 +498,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 5 | 0 | 0 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 8 | 0 | 0 | 0 | | | [@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 | 1 | 8 | 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 | @@ -519,29 +526,30 @@ 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) | - | 58 | 1 | 58 | 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) | - | 68 | 0 | 62 | 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 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 147 | 0 | 125 | 0 | -| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 528 | 0 | 515 | 0 | +| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 532 | 0 | 519 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 67 | 0 | 37 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 28 | 0 | 21 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 69 | 0 | 65 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 35 | 0 | 23 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 62 | 0 | 49 | 0 | -| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 207 | 10 | 160 | 0 | +| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 207 | 0 | 160 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 26 | 0 | 23 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 120 | 0 | 116 | 0 | -| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 31 | 2 | 29 | 0 | +| | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 31 | 0 | 29 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 54 | 0 | 51 | 1 | | | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | - | 31 | 0 | 30 | 1 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 10 | 0 | 7 | 1 | @@ -586,29 +594,31 @@ 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) | - | 130 | 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 | 2 | 35 | 0 | +| | [@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 | 1 | 151 | 3 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 155 | 0 | 151 | 3 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 6 | 0 | 2 | 0 | diff --git a/api_docs/presentation_util.devdocs.json b/api_docs/presentation_util.devdocs.json index fa2eee15cf28c..9582e337fbb17 100644 --- a/api_docs/presentation_util.devdocs.json +++ b/api_docs/presentation_util.devdocs.json @@ -3785,13 +3785,10 @@ { "parentPluginId": "presentationUtil", "id": "def-common.projects.DEFER_BELOW_FOLD.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/presentation_util/common/labs.ts", "deprecated": false, "trackAdoption": false @@ -3799,13 +3796,10 @@ { "parentPluginId": "presentationUtil", "id": "def-common.projects.DEFER_BELOW_FOLD.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/presentation_util/common/labs.ts", "deprecated": false, "trackAdoption": false @@ -3896,13 +3890,10 @@ { "parentPluginId": "presentationUtil", "id": "def-common.projects.DASHBOARD_CONTROLS.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/presentation_util/common/labs.ts", "deprecated": false, "trackAdoption": false @@ -3910,13 +3901,10 @@ { "parentPluginId": "presentationUtil", "id": "def-common.projects.DASHBOARD_CONTROLS.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/presentation_util/common/labs.ts", "deprecated": false, "trackAdoption": false @@ -4007,13 +3995,10 @@ { "parentPluginId": "presentationUtil", "id": "def-common.projects.BY_VALUE_EMBEDDABLE.name", - "type": "Any", + "type": "string", "tags": [], "label": "name", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/presentation_util/common/labs.ts", "deprecated": false, "trackAdoption": false @@ -4021,13 +4006,10 @@ { "parentPluginId": "presentationUtil", "id": "def-common.projects.BY_VALUE_EMBEDDABLE.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "src/plugins/presentation_util/common/labs.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 041e9bb457efe..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kib | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 218 | 8 | 164 | 11 | +| 218 | 2 | 164 | 11 | ## Client diff --git a/api_docs/profiling.devdocs.json b/api_docs/profiling.devdocs.json index 11469e74de24f..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", @@ -335,13 +302,10 @@ { "parentPluginId": "profiling", "id": "def-common.NOT_AVAILABLE_LABEL", - "type": "Any", + "type": "string", "tags": [], "label": "NOT_AVAILABLE_LABEL", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/profiling/common/index.ts", "deprecated": false, "trackAdoption": false, diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 796304b388ec8..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-22 +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 | 2 | 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 d158b823aa966..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-22 +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 6d39091749d8c..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-22 +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 c835f9274e239..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-22 +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 7a7dd9b1254ce..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-22 +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 245417dc183ff..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-22 +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 5a8562e32b3bf..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-22 +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 ab4912dce6121..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-22 +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 caec5c09c86f3..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-22 +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 46e4834cf5c93..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-22 +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 6b22233136fad..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-22 +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 c88777ba19588..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-22 +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 4e7b2321a2786..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-22 +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 f264d22440b01..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-22 +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 bf9a4ea869395..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-22 +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 555399636c3d2..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, @@ -390,357 +390,6 @@ } ], "initialIsOpen": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService", - "type": "Class", - "tags": [], - "label": "UpsellingService", - "description": [], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.sections$", - "type": "Object", - "tags": [], - "label": "sections$", - "description": [], - "signature": [ - "Observable", - ">>" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.pages$", - "type": "Object", - "tags": [], - "label": "pages$", - "description": [], - "signature": [ - "Observable", - ">>" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.messages$", - "type": "Object", - "tags": [], - "label": "messages$", - "description": [], - "signature": [ - "Observable", - ">" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.Unnamed", - "type": "Function", - "tags": [], - "label": "Constructor", - "description": [], - "signature": [ - "any" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.setSections", - "type": "Function", - "tags": [], - "label": "setSections", - "description": [], - "signature": [ - "(sections: Partial>>) => void" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.setSections.$1", - "type": "Object", - "tags": [], - "label": "sections", - "description": [], - "signature": [ - "Partial>>" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.setPages", - "type": "Function", - "tags": [], - "label": "setPages", - "description": [], - "signature": [ - "(pages: Partial>>) => void" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.setPages.$1", - "type": "Object", - "tags": [], - "label": "pages", - "description": [], - "signature": [ - "Partial>>" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.setMessages", - "type": "Function", - "tags": [], - "label": "setMessages", - "description": [], - "signature": [ - "(messages: Partial>) => void" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.setMessages.$1", - "type": "Object", - "tags": [], - "label": "messages", - "description": [], - "signature": [ - "Partial>" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.isPageUpsellable", - "type": "Function", - "tags": [], - "label": "isPageUpsellable", - "description": [], - "signature": [ - "(id: ", - { - "pluginId": "@kbn/security-solution-navigation", - "scope": "common", - "docId": "kibKbnSecuritySolutionNavigationPluginApi", - "section": "def-common.SecurityPageName", - "text": "SecurityPageName" - }, - ") => boolean" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.isPageUpsellable.$1", - "type": "Enum", - "tags": [], - "label": "id", - "description": [], - "signature": [ - { - "pluginId": "@kbn/security-solution-navigation", - "scope": "common", - "docId": "kibKbnSecuritySolutionNavigationPluginApi", - "section": "def-common.SecurityPageName", - "text": "SecurityPageName" - } - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.getPageUpselling", - "type": "Function", - "tags": [], - "label": "getPageUpselling", - "description": [], - "signature": [ - "(id: ", - { - "pluginId": "@kbn/security-solution-navigation", - "scope": "common", - "docId": "kibKbnSecuritySolutionNavigationPluginApi", - "section": "def-common.SecurityPageName", - "text": "SecurityPageName" - }, - ") => React.ComponentType<{}> | undefined" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.getPageUpselling.$1", - "type": "Enum", - "tags": [], - "label": "id", - "description": [], - "signature": [ - { - "pluginId": "@kbn/security-solution-navigation", - "scope": "common", - "docId": "kibKbnSecuritySolutionNavigationPluginApi", - "section": "def-common.SecurityPageName", - "text": "SecurityPageName" - } - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.getSectionsValue", - "type": "Function", - "tags": [], - "label": "getSectionsValue", - "description": [], - "signature": [ - "() => Map<", - { - "pluginId": "securitySolution", - "scope": "public", - "docId": "kibSecuritySolutionPluginApi", - "section": "def-public.UpsellingSectionId", - "text": "UpsellingSectionId" - }, - ", React.ComponentType<{}>>" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingService.getMessagesValue", - "type": "Function", - "tags": [], - "label": "getMessagesValue", - "description": [], - "signature": [ - "() => Map<\"investigation_guide\", string>" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - } - ], - "initialIsOpen": false } ], "functions": [], @@ -831,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, @@ -911,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, @@ -2061,53 +1710,7 @@ } ], "enums": [], - "misc": [ - { - "parentPluginId": "securitySolution", - "id": "def-public.PageUpsellings", - "type": "Type", - "tags": [], - "label": "PageUpsellings", - "description": [], - "signature": [ - "{ administration?: React.ComponentType<{}> | undefined; alerts?: React.ComponentType<{}> | undefined; assets?: React.ComponentType<{}> | undefined; blocklist?: React.ComponentType<{}> | undefined; cases?: React.ComponentType<{}> | undefined; cases_configure?: React.ComponentType<{}> | undefined; cases_create?: React.ComponentType<{}> | undefined; \"cloud_security_posture-benchmarks\"?: React.ComponentType<{}> | undefined; \"cloud_security_posture-dashboard\"?: React.ComponentType<{}> | undefined; \"cloud_security_posture-findings\"?: React.ComponentType<{}> | undefined; \"cloud_security_posture-rules\"?: React.ComponentType<{}> | undefined; cloud_defend?: React.ComponentType<{}> | undefined; \"cloud_defend-policies\"?: React.ComponentType<{}> | undefined; dashboards?: React.ComponentType<{}> | undefined; data_quality?: React.ComponentType<{}> | undefined; detections?: React.ComponentType<{}> | undefined; detection_response?: React.ComponentType<{}> | undefined; endpoints?: React.ComponentType<{}> | undefined; event_filters?: React.ComponentType<{}> | undefined; exceptions?: React.ComponentType<{}> | undefined; explore?: React.ComponentType<{}> | undefined; host_isolation_exceptions?: React.ComponentType<{}> | undefined; hosts?: React.ComponentType<{}> | undefined; \"hosts-anomalies\"?: React.ComponentType<{}> | undefined; \"hosts-risk\"?: React.ComponentType<{}> | undefined; \"hosts-events\"?: React.ComponentType<{}> | undefined; investigations?: React.ComponentType<{}> | undefined; kubernetes?: React.ComponentType<{}> | undefined; get_started?: React.ComponentType<{}> | undefined; \"machine_learning-landing\"?: React.ComponentType<{}> | undefined; network?: React.ComponentType<{}> | undefined; \"network-anomalies\"?: React.ComponentType<{}> | undefined; \"network-dns\"?: React.ComponentType<{}> | undefined; \"network-events\"?: React.ComponentType<{}> | undefined; \"network-http\"?: React.ComponentType<{}> | undefined; \"network-tls\"?: React.ComponentType<{}> | undefined; \"\"?: React.ComponentType<{}> | undefined; overview?: React.ComponentType<{}> | undefined; policy?: React.ComponentType<{}> | undefined; project_settings?: React.ComponentType<{}> | undefined; response_actions_history?: React.ComponentType<{}> | undefined; rules?: React.ComponentType<{}> | undefined; \"rules-add\"?: React.ComponentType<{}> | undefined; \"rules-create\"?: React.ComponentType<{}> | undefined; \"rules-landing\"?: React.ComponentType<{}> | undefined; sessions?: React.ComponentType<{}> | undefined; threat_intelligence?: React.ComponentType<{}> | undefined; timelines?: React.ComponentType<{}> | undefined; \"timelines-templates\"?: React.ComponentType<{}> | undefined; trusted_apps?: React.ComponentType<{}> | undefined; uncommon_processes?: React.ComponentType<{}> | undefined; users?: React.ComponentType<{}> | undefined; \"users-anomalies\"?: React.ComponentType<{}> | undefined; \"users-authentications\"?: React.ComponentType<{}> | undefined; \"users-events\"?: React.ComponentType<{}> | undefined; \"users-risk\"?: React.ComponentType<{}> | undefined; entity_analytics?: React.ComponentType<{}> | undefined; \"entity_analytics-management\"?: React.ComponentType<{}> | undefined; \"coverage-overview\"?: React.ComponentType<{}> | undefined; }" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.SectionUpsellings", - "type": "Type", - "tags": [], - "label": "SectionUpsellings", - "description": [], - "signature": [ - "{ entity_analytics_panel?: React.ComponentType<{}> | undefined; endpointPolicyProtections?: React.ComponentType<{}> | undefined; osquery_automated_response_actions?: React.ComponentType<{}> | undefined; }" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "securitySolution", - "id": "def-public.UpsellingSectionId", - "type": "Type", - "tags": [], - "label": "UpsellingSectionId", - "description": [], - "signature": [ - "\"entity_analytics_panel\" | \"endpointPolicyProtections\" | \"osquery_automated_response_actions\"" - ], - "path": "x-pack/plugins/security_solution/public/common/lib/upsellings/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], + "misc": [], "objects": [], "setup": { "parentPluginId": "securitySolution", @@ -2242,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", @@ -2335,13 +1970,7 @@ "description": [], "signature": [ "() => ", - { - "pluginId": "securitySolution", - "scope": "public", - "docId": "kibSecuritySolutionPluginApi", - "section": "def-public.UpsellingService", - "text": "UpsellingService" - } + "UpsellingService" ], "path": "x-pack/plugins/security_solution/public/types.ts", "deprecated": false, @@ -3163,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", @@ -3188,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 } @@ -3309,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", @@ -3390,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, @@ -3429,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", @@ -3460,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 3130e47267169..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-22 +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 | |-------------------|-----------|------------------------|-----------------| -| 195 | 3 | 129 | 34 | +| 170 | 0 | 104 | 32 | ## Client @@ -37,9 +37,6 @@ Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/secur ### Interfaces -### Consts, variables and types - - ## Server ### Setup diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index 9fe8027ee8d04..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-22 +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 6a4abbd44713f..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-22 +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 e641d33506a55..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-22 +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 ab041cda0d2b1..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-22 +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 fc0aa2be70988..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-22 +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 7ac0882b8cd6d..ad8cfcd6b086e 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,14 +8,14 @@ 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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; -Contact [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/teams/sec-cloudnative-integrations) for questions regarding this plugin. +Contact [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 84d0a9fa5c1d9..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-22 +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 3832f4e7a8327..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-22 +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 1f7dad2e6e0dd..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-22 +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 9f04183dcdfe0..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-22 +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 a47fab157577f..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-22 +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 b55121b4ac525..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-22 +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 e22377f07c12f..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-22 +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 cc6341caa41be..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-22 +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 4a2192c588ba2..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-22 +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 9db6fba20450c..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-22 +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 a63a0ddca50fc..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-22 +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 bd49514e781be..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-22 +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 49b0364fa1008..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-22 +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 85a1836888377..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.devdocs.json b/api_docs/triggers_actions_ui.devdocs.json index 5ad44fa0f8e76..9d84568f429d3 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -819,7 +819,7 @@ "section": "def-public.TIME_UNITS", "text": "TIME_UNITS" }, - ", timeValue: string) => any" + ", timeValue: string) => string" ], "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/get_time_unit_label.ts", "deprecated": false, @@ -6086,13 +6086,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.connectorDeprecatedMessage", - "type": "Any", + "type": "string", "tags": [], "label": "connectorDeprecatedMessage", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/connectors_selection.tsx", "deprecated": false, "trackAdoption": false, @@ -6122,13 +6119,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.deprecatedMessage", - "type": "Any", + "type": "string", "tags": [], "label": "deprecatedMessage", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/connectors_selection.tsx", "deprecated": false, "trackAdoption": false, @@ -6704,13 +6698,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.builtInComparators.COMPARATORS.GREATER_THAN.text", - "type": "Any", + "type": "string", "tags": [], "label": "text", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/constants/comparators.ts", "deprecated": false, "trackAdoption": false @@ -6762,13 +6753,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.builtInComparators.COMPARATORS.GREATER_THAN_OR_EQUALS.text", - "type": "Any", + "type": "string", "tags": [], "label": "text", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/constants/comparators.ts", "deprecated": false, "trackAdoption": false @@ -6820,13 +6808,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.builtInComparators.COMPARATORS.LESS_THAN.text", - "type": "Any", + "type": "string", "tags": [], "label": "text", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/constants/comparators.ts", "deprecated": false, "trackAdoption": false @@ -6878,13 +6863,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.builtInComparators.COMPARATORS.LESS_THAN_OR_EQUALS.text", - "type": "Any", + "type": "string", "tags": [], "label": "text", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/constants/comparators.ts", "deprecated": false, "trackAdoption": false @@ -6936,13 +6918,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.builtInComparators.COMPARATORS.BETWEEN.text", - "type": "Any", + "type": "string", "tags": [], "label": "text", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/constants/comparators.ts", "deprecated": false, "trackAdoption": false @@ -6994,13 +6973,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.builtInComparators.COMPARATORS.NOT_BETWEEN.text", - "type": "Any", + "type": "string", "tags": [], "label": "text", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/constants/comparators.ts", "deprecated": false, "trackAdoption": false @@ -7066,13 +7042,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.builtInGroupByTypes.all.text", - "type": "Any", + "type": "string", "tags": [], "label": "text", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/constants/group_by_types.ts", "deprecated": false, "trackAdoption": false @@ -7132,13 +7105,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.builtInGroupByTypes.top.text", - "type": "Any", + "type": "string", "tags": [], "label": "text", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/constants/group_by_types.ts", "deprecated": false, "trackAdoption": false @@ -7201,13 +7171,10 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.firstFieldOption.text", - "type": "Any", + "type": "string", "tags": [], "label": "text", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/triggers_actions_ui/public/common/index_controls/index.ts", "deprecated": false, "trackAdoption": false @@ -8222,6 +8189,42 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.TriggersAndActionsUIPublicPluginStart.getGlobalRuleEventLogList", + "type": "Function", + "tags": [], + "label": "getGlobalRuleEventLogList", + "description": [], + "signature": [ + "(props: ", + "GlobalRuleEventLogListProps", + ") => React.ReactElement<", + "GlobalRuleEventLogListProps", + ", string | React.JSXElementConstructor>" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.TriggersAndActionsUIPublicPluginStart.getGlobalRuleEventLogList.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "GlobalRuleEventLogListProps" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "lifecycle": "start", @@ -8874,7 +8877,7 @@ "label": "getTooManyIntervalsErrorMessage", "description": [], "signature": [ - "(intervals: number, maxIntervals: number) => any" + "(intervals: number, maxIntervals: number) => string" ], "path": "x-pack/plugins/triggers_actions_ui/common/data/lib/date_range_info.ts", "deprecated": false, diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 72462a186cd85..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 571 | 12 | 545 | 50 | +| 573 | 1 | 547 | 51 | ## Client diff --git a/api_docs/ui_actions.devdocs.json b/api_docs/ui_actions.devdocs.json index 466038b9bb162..7c43d3c333e58 100644 --- a/api_docs/ui_actions.devdocs.json +++ b/api_docs/ui_actions.devdocs.json @@ -2543,13 +2543,10 @@ { "parentPluginId": "uiActions", "id": "def-public.rowClickTrigger.title", - "type": "Any", + "type": "string", "tags": [], "label": "title", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-ui-actions-browser/src/triggers/row_click_trigger.ts", "deprecated": false, "trackAdoption": false @@ -2557,13 +2554,10 @@ { "parentPluginId": "uiActions", "id": "def-public.rowClickTrigger.description", - "type": "Any", + "type": "string", "tags": [], "label": "description", "description": [], - "signature": [ - "any" - ], "path": "packages/kbn-ui-actions-browser/src/triggers/row_click_trigger.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 61fd92f9d3061..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-22 +date: 2023-09-04 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.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 | |-------------------|-----------|------------------------|-----------------| -| 145 | 2 | 103 | 9 | +| 145 | 0 | 103 | 9 | ## Client diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 57d8b452493bd..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-22 +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 da2cdd06a97aa..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-22 +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 4cf3f2c105d74..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, @@ -473,9 +624,9 @@ "[] | undefined; prependFilterBar?: React.ReactNode; isRefreshPaused?: boolean | undefined; dateRangeFrom?: string | undefined; dateRangeTo?: string | undefined; showSaveQuery?: boolean | undefined; savedQuery?: ", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, " | undefined; onQueryChange?: ((payload: { dateRange: ", @@ -513,17 +664,17 @@ " | QT | undefined; }, isUpdate?: boolean | undefined) => void) | undefined; onSaved?: ((savedQuery: ", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ") => void) | undefined; onSavedQueryUpdated?: ((savedQuery: ", { "pluginId": "data", - "scope": "public", + "scope": "common", "docId": "kibDataQueryPluginApi", - "section": "def-public.SavedQuery", + "section": "def-common.SavedQuery", "text": "SavedQuery" }, ") => void) | undefined; onTimeRangeChange?: ((payload: { dateRange: ", @@ -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 cec7ebcd68d21..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-22 +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 7fdcb2c3d8177..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-22 +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 9318b8462b02d..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-22 +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 1480341356374..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-22 +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 3308b197c53cd..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-22 +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 58f5395038666..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-22 +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 e392681c5af69..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-22 +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 4315ed076acb4..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-22 +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 bf7c8d90d9d1f..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-22 +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 12b55329dbfb1..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-22 +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 0797845860ccf..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-22 +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 912056fc65e2e..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-22 +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 20f3af522d34d..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-22 +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 bbb883d7dfdd3..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-22 +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 85f49c4d6a0ca..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-22 +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.devdocs.json b/api_docs/vis_type_xy.devdocs.json index 93579858eaf00..de45fb3d360e0 100644 --- a/api_docs/vis_type_xy.devdocs.json +++ b/api_docs/vis_type_xy.devdocs.json @@ -11,7 +11,7 @@ "label": "getPositions", "description": [], "signature": [ - "() => ({ text: any; value: \"top\"; } | { text: any; value: \"left\"; } | { text: any; value: \"right\"; } | { text: any; value: \"bottom\"; })[]" + "() => ({ text: string; value: \"top\"; } | { text: string; value: \"left\"; } | { text: string; value: \"right\"; } | { text: string; value: \"bottom\"; })[]" ], "path": "src/plugins/vis_types/xy/public/editor/positions.ts", "deprecated": false, @@ -28,7 +28,7 @@ "label": "getScaleTypes", "description": [], "signature": [ - "() => { text: any; value: ", + "() => { text: string; value: ", { "pluginId": "visTypeXy", "scope": "public", diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 6f9e9cdbd42bc..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-22 +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 152024c118779..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, @@ -6715,7 +6715,7 @@ "section": "def-common.SavedObjectReference", "text": "SavedObjectReference" }, - "[]; }; isEditable: () => Promise; getDisplayName: () => any; createFromSavedObject: (savedObjectId: string, input: Partial<", + "[]; }; isEditable: () => Promise; getDisplayName: () => string; createFromSavedObject: (savedObjectId: string, input: Partial<", { "pluginId": "visualizations", "scope": "public", @@ -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 585dfa1f89ecc..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-22 +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 534e34ba27008..00637fb1a039b 100644 --- a/catalog-info.yaml +++ b/catalog-info.yaml @@ -50,7 +50,7 @@ spec: description: Pipeline that tests the service integration in various environments spec: repository: elastic/kibana - pipeline_file: ./.buildkite/pipelines/pipeline.kibana-tests.yaml + pipeline_file: ./.buildkite/pipelines/quality-gates/pipeline.kibana-tests.yaml provider_settings: trigger_mode: none teams: @@ -68,3 +68,95 @@ spec: access_level: BUILD_AND_READ everyone: access_level: READ_ONLY + +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: Kibana-UI-Service + description: Kibana UI Service provides the UX for visualizing Elasticsearch data. It is comprised of a client side for presentation and user event handling and a server side application for UX servicing and interaction with Elasticsearch. + annotations: + backstage.io/source-location: url:https://github.com/elastic/kibana/tree/main + github.com/project-slug: elastic/kibana + github.com/team-slug: elastic/kibana-tech-leads + buildkite.com/project-slug: elastic/kibana + tags: + - typescript + - javascript + - dashboards + - metrics + - visualizations + - observability + links: + - title: Documentation + url: https://www.elastic.co/guide/en/kibana/current/index.html +spec: + type: service + owner: group:kibana-tech-leads + lifecycle: production + system: control-plane + +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: Kibana-Background-Tasks-Service + description: Kibana Background Tasks Service provides additional task processing parallelism for an instance of the Kibana UI Service. It is comprised of the same codebase as Kibana UI Service but is launched with an alternative configuration. + annotations: + backstage.io/source-location: url:https://github.com/elastic/kibana/tree/main + github.com/project-slug: elastic/kibana + github.com/team-slug: elastic/kibana-tech-leads + buildkite.com/project-slug: elastic/kibana + tags: + - typescript + - javascript + - dashboards + - metrics + - visualizations + - observability + links: + - title: Documentation + url: https://www.elastic.co/guide/en/kibana/current/index.html +spec: + type: service + owner: group:kibana-tech-leads + 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 bb16628f3f5eb..7a1da782855bd 100644 --- a/config/serverless.es.yml +++ b/config/serverless.es.yml @@ -9,7 +9,12 @@ xpack.observability.enabled: false xpack.securitySolution.enabled: false xpack.serverless.observability.enabled: false xpack.uptime.enabled: false -enterpriseSearch.enabled: false +enterpriseSearch.enabled: true +enterpriseSearch.canDeployEntSearch: false +enterpriseSearch.hasConnectors: true +enterpriseSearch.hasNativeConnectors: false +enterpriseSearch.hasWebCrawler: false +enterpriseSearch.ui.enabled: false monitoring.ui.enabled: false xpack.fleet.enabled: false @@ -27,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 e548146f39de5..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 @@ -37,6 +38,8 @@ xpack.license_management.enabled: false xpack.index_management.enableIndexActions: false # Disable legacy index templates from Index Management UI xpack.index_management.enableLegacyTemplates: false +# Disable index stats information from Index Management UI +xpack.index_management.enableIndexStats: false # Keep deeplinks visible so that they are shown in the sidenav dev_tools.deeplinks.navLinkStatus: visible @@ -48,6 +51,9 @@ xpack.cloud_integrations.data_migration.enabled: false data.search.sessions.enabled: false advanced_settings.enabled: false +# Disable the browser-side functionality that depends on SecurityCheckupGetStateRoutes +xpack.security.showInsecureClusterWarning: false + # Disable UI of security management plugins xpack.security.ui.userManagementEnabled: false xpack.security.ui.roleManagementEnabled: false @@ -81,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 @@ -107,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/connectors/connector-apis-passthru.asciidoc b/docs/api-generated/connectors/connector-apis-passthru.asciidoc index 64bf78a2b66ed..f5128f88f1b1e 100644 --- a/docs/api-generated/connectors/connector-apis-passthru.asciidoc +++ b/docs/api-generated/connectors/connector-apis-passthru.asciidoc @@ -1010,6 +1010,7 @@ Any modifications made to this file will be overwritten.
  • config_properties_servicenow - Connector request properties for a ServiceNow ITSM connector
  • config_properties_servicenow_itom - Connector request properties for a ServiceNow ITSM connector
  • config_properties_swimlane - Connector request properties for a Swimlane connector
  • +
  • config_properties_webhook - Connector request properties for a Webhook connector
  • connector_response_properties - Connector response properties
  • connector_response_properties_cases_webhook - Connector request properties for a Webhook - Case Management connector
  • connector_response_properties_email - Connector response properties for an email connector
  • @@ -1093,6 +1094,7 @@ Any modifications made to this file will be overwritten.
  • secrets_properties_slack_api - Connector secrets properties for a Web API Slack connector
  • secrets_properties_slack_webhook - Connector secrets properties for a Webhook Slack connector
  • secrets_properties_swimlane - Connector secrets properties for a Swimlane connector
  • +
  • secrets_properties_webhook - Connector secrets properties for a Webhook connector
  • updateConnector_400_response -
  • update_connector_request_cases_webhook - Update Webhook - Case Managment connector request
  • update_connector_request_index - Update index connector request
  • @@ -1450,6 +1452,28 @@ Any modifications made to this file will be overwritten.
    mappings (optional)
    +
    +

    config_properties_webhook - Connector request properties for a Webhook connector Up

    +
    Defines properties for connectors when type is .webhook.
    +
    +
    authType (optional)
    String The type of authentication to use: basic, SSL, or none.
    +
    Enum:
    +
    webhook-authentication-basic
    webhook-authentication-ssl
    null
    +
    ca (optional)
    String A base64 encoded version of the certificate authority file that the connector can trust to sign and validate certificates. This option is available for all authentication types.
    +
    certType (optional)
    String If the authType is webhook-authentication-ssl, specifies whether the certificate authentication data is in a CRT and key file format or a PFX file format.
    +
    Enum:
    +
    ssl-crt-key
    ssl-pfx
    +
    hasAuth (optional)
    Boolean If true, a user name and password must be provided for login type authentication.
    +
    headers (optional)
    Object A set of key-value pairs sent as headers with the request.
    +
    method (optional)
    String The HTTP request method, either post or put.
    +
    Enum:
    +
    post
    put
    +
    url (optional)
    String The request URL. If you are using the xpack.actions.allowedHosts setting, add the hostname to the allowed hosts.
    +
    verificationMode (optional)
    String Controls the verification of certificates. Use full to validate that the certificate has an issue date within the not_before and not_after dates, chains to a trusted certificate authority (CA), and has a hostname or IP address that matches the names within the certificate. Use certificate to validate the certificate and verify that it is signed by a trusted authority; this option does not check the certificate hostname. Use none to skip certificate validation.
    +
    Enum:
    +
    certificate
    full
    none
    +
    +

    connector_response_properties - Connector response properties Up

    The properties vary depending on the connector type.
    @@ -1723,7 +1747,7 @@ Any modifications made to this file will be overwritten.

    connector_response_properties_webhook - Connector response properties for a Webhook connector Up

    -
    config
    map[String, oas_any_type_not_mapped] Defines properties for connectors when type is .webhook.
    +
    config
    connector_type_id
    String The type of connector.
    Enum:
    .webhook
    @@ -1959,12 +1983,12 @@ Any modifications made to this file will be overwritten.

    create_connector_request_webhook - Create Webhook connector request Up

    The Webhook connector uses axios to send a POST or PUT request to a web service.
    -
    config
    map[String, oas_any_type_not_mapped] Defines properties for connectors when type is .webhook.
    +
    config
    connector_type_id
    String The type of connector.
    Enum:
    .webhook
    name
    String The display name for the connector.
    -
    secrets
    map[String, oas_any_type_not_mapped] Defines secrets for connectors when type is .webhook.
    +
    secrets
    @@ -2392,6 +2416,17 @@ Any modifications made to this file will be overwritten.
    apiToken (optional)
    String Swimlane API authentication token.
    +
    +

    secrets_properties_webhook - Connector secrets properties for a Webhook connector Up

    +
    Defines secrets for connectors when type is .webhook.
    +
    +
    crt (optional)
    String If authType is webhook-authentication-ssl and certType is ssl-crt-key, it is a base64 encoded version of the CRT or CERT file.
    +
    key (optional)
    String If authType is webhook-authentication-ssl and certType is ssl-crt-key, it is a base64 encoded version of the KEY file.
    +
    pfx (optional)
    String If authType is webhook-authentication-ssl and certType is ssl-pfx, it is a base64 encoded version of the PFX or P12 file.
    +
    password (optional)
    String The password for HTTP basic authentication or the passphrase for the SSL certificate files. If hasAuth is set to true and authType is webhook-authentication-basic, this property is required.
    +
    user (optional)
    String The username for HTTP basic authentication. If hasAuth is set to true and authType is webhook-authentication-basic, this property is required.
    +
    +

    updateConnector_400_response - Up

    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/apm/api.asciidoc b/docs/apm/api.asciidoc index 9058b29f0cb8a..fb672b2884af2 100644 --- a/docs/apm/api.asciidoc +++ b/docs/apm/api.asciidoc @@ -11,7 +11,6 @@ Some APM app features are provided via a REST API: * <> * <> * <> -* <> * <> [float] @@ -716,219 +715,6 @@ curl -X DELETE "http://localhost:5601/api/apm/sourcemaps/apm:foo-1.0.0-644fd5a9" ******************************************************* //// -[role="xpack"] -[[android-sourcemap-api]] -=== Android source map API - -IMPORTANT: This endpoint is only compatible with the -{apm-guide-ref}/index.html[APM integration for Elastic Agent]. - -An Android source map (generated using Android's https://developer.android.com/build/shrink-code[R8 tool]) -allows obfuscated app stacktraces to be mapped back to original source code -- -allowing you to maintain the size and security of minimized code, without losing the ability to debug your application. - -For best results, uploading source maps should become a part of your deployment procedure, -and not something you only do when you see unhelpful errors. -That’s because uploading source maps after errors happen won’t make old errors magically readable -- -errors must occur again for source mapping to occur. - -The following APIs are available: - -* <> -* <> -* <> - -[float] -[[use-android-sourcemap-api]] -==== How to use APM APIs - -.Expand for required headers, privileges, and usage details -[%collapsible%closed] -====== -include::api.asciidoc[tag=using-the-APIs] -====== - -//// -******************************************************* -//// - -[[android-sourcemap-post]] -==== Create or update an Android source map - -Create or update an Android source map for a specific app and version. - -[[android-sourcemap-post-privs]] -===== Privileges - -The user accessing this endpoint requires `All` Kibana privileges for the {beat_kib_app} feature. -For more information, see <>. - -[[android-sourcemap-post-req]] -===== Request - -`POST /api/apm/androidmaps` - -[role="child_attributes"] -[[android-sourcemap-post-req-body]] -===== Request body - -`service_name`:: -(required, string) The name of the Android app that the map should apply to. - -`service_version`:: -(required, string) The version of the Android app that the map should apply to. - -`map_file`:: -(required, string or file upload) The R8-generated map. - -[[android-sourcemap-post-example]] -===== Examples - -The following example uploads a source map for a app named `foo` and a service version of `1.0.0`: - -[source,curl] --------------------------------------------------- -curl -X POST "http://localhost:5601/api/apm/androidmaps" \ --H 'Content-Type: multipart/form-data' \ --H 'kbn-xsrf: true' \ --H 'Authorization: ApiKey ${YOUR_API_KEY}' \ --F 'service_name="foo"' \ --F 'service_version="1.0.0"' \ --F 'map_file=@"/Path/to/the/file/mapping.txt"' --------------------------------------------------- - -[[android-sourcemap-post-body]] -===== Response body - -[source,js] --------------------------------------------------- -{ - "type": "sourcemap", - "identifier": "foo-1.0.0-android", - "relative_url": "/api/fleet/artifacts/foo-1.0.0-android/644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456", - "body": "eJyFkL1OwzAUhd/Fc+MbYMuCEBIbHRjKgBgc96R16tiWr1OQqr47NwqJxEK3q/PzWccXxchnZ7E1A1SjuhjVZtF2yOxiEPlO17oWox3D3uPFeSRTjmJQARfCPeiAgGx8NTKsYdAc1T3rwaSJGcds8Sp3c1HnhfywUZ3QhMTFFGepZxqMC9oex3CS9tpk1XyozgOlmoVKuJX1DqEQZ0su7PGtLU+V/3JPKc3cL7TJ2FNDRPov4bFta3MDM4f7W69lpJjLO9qdK8bzVPhcJz3HUCQ4LbO/p5hCSC4cZPByrp/wFqOklbpefwAhzpqI", - "created": "2021-07-09T20:47:44.812Z", - "id": "apm:foo-1.0.0-android-644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456", - "compressionAlgorithm": "zlib", - "decodedSha256": "644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456", - "decodedSize": 441, - "encodedSha256": "024c72749c3e3dd411b103f7040ae62633558608f480bce4b108cf5b2275bd24", - "encodedSize": 237, - "encryptionAlgorithm": "none", - "packageName": "apm" -} --------------------------------------------------- - -//// -******************************************************* -//// - -[[android-sourcemap-get]] -==== Get source maps - -Returns an array of Fleet artifacts, including source map uploads. - -[[android-sourcemap-get-privs]] -===== Privileges - -The user accessing this endpoint requires `Read` or `All` Kibana privileges for the {beat_kib_app} feature. -For more information, see <>. - -[[android-sourcemap-get-req]] -===== Request - -`GET /api/apm/sourcemaps` - -[[android-sourcemap-get-example]] -===== Example - -The following example requests all uploaded source maps: - -[source,curl] --------------------------------------------------- -curl -X GET "http://localhost:5601/api/apm/sourcemaps" \ --H 'Content-Type: application/json' \ --H 'kbn-xsrf: true' \ --H 'Authorization: ApiKey ${YOUR_API_KEY}' --------------------------------------------------- - -[[android-sourcemap-get-body]] -===== Response body - -[source,js] --------------------------------------------------- -{ - "artifacts": [ - { - "type": "sourcemap", - "identifier": "foo-1.0.0-android", - "relative_url": "/api/fleet/artifacts/foo-1.0.0-android/644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456", - "body": { - "serviceName": "foo", - "serviceVersion": "1.0.0", - "bundleFilepath": "android", - "sourceMap": "# compiler: R8\n# compiler_version: 3.2.47\n# min_api: 26\n..." - }, - "created": "2021-07-09T20:47:44.812Z", - "id": "apm:foo-1.0.0-android-644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456", - "compressionAlgorithm": "zlib", - "decodedSha256": "644fd5a997d1ddd90ee131ba18e2b3d03931d89dd1fe4599143c0b3264b3e456", - "decodedSize": 441, - "encodedSha256": "024c72749c3e3dd411b103f7040ae62633558608f480bce4b108cf5b2275bd24", - "encodedSize": 237, - "encryptionAlgorithm": "none", - "packageName": "apm" - } - ] -} --------------------------------------------------- - -//// -******************************************************* -//// - -[[android-sourcemap-delete]] -==== Delete source map - -Delete a previously uploaded source map. - -[[android-sourcemap-delete-privs]] -===== Privileges - -The user accessing this endpoint requires `All` Kibana privileges for the {beat_kib_app} feature. -For more information, see <>. - -[[android-sourcemap-delete-req]] -===== Request - -`DELETE /api/apm/sourcemaps/:id` - -[[android-sourcemap-delete-example]] -===== Example - -The following example deletes a source map with an id of `apm:foo-1.0.0-android-644fd5a9`: - -[source,curl] --------------------------------------------------- -curl -X DELETE "http://localhost:5601/api/apm/sourcemaps/apm:foo-1.0.0-android-644fd5a9" \ --H 'Content-Type: application/json' \ --H 'kbn-xsrf: true' \ --H 'Authorization: ApiKey ${YOUR_API_KEY}' --------------------------------------------------- - -[[android-sourcemap-delete-body]] -===== Response body - -[source,js] --------------------------------------------------- -{} --------------------------------------------------- - -//// -******************************************************* -******************************************************* -//// - [role="xpack"] [[agent-key-api]] === APM agent Key API 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/action-types/webhook.asciidoc b/docs/management/connectors/action-types/webhook.asciidoc index 5424eb87c3ae4..1868f96d14c1d 100644 --- a/docs/management/connectors/action-types/webhook.asciidoc +++ b/docs/management/connectors/action-types/webhook.asciidoc @@ -3,6 +3,10 @@ ++++ Webhook ++++ +:frontmatter-description: Add a connector that can send requests to a web service. +:frontmatter-tags-products: [alerting] +:frontmatter-tags-content-type: [how-to] +:frontmatter-tags-user-goals: [configure] The Webhook connector uses https://github.com/axios/axios[axios] to send a POST or PUT request to a web service. @@ -15,6 +19,7 @@ or as needed when you're creating a rule. For example: [role="screenshot"] image::management/connectors/images/webhook-connector.png[Webhook connector] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. [float] [[webhook-connector-configuration]] @@ -23,49 +28,27 @@ image::management/connectors/images/webhook-connector.png[Webhook connector] Webhook connectors have the following configuration properties: Name:: The name of the connector. -URL:: The request URL. If you are using the <> setting, make sure the hostname is added to the allowed hosts. -Method:: HTTP request method, either `post`(default) or `put`. -Headers:: A set of key-value pairs sent as headers with the request -Require authentication:: If true, a username and password for login type authentication must be provided. -Username:: Username for HTTP basic authentication. -Password:: Password for HTTP basic authentication. - -[float] -[[preconfigured-webhook-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] +Method:: The HTTP request method, either `post`(default) or `put`. +URL:: The request URL. If you are using the <> setting, make sure the hostname is added to the allowed hosts. +Authentication:: +The authentication type: none, basic, or SSL. +If you choose basic authentication, you must provide a user name and password. +If you choose SSL authentication, you must provide SSL server certificate authentication data in a CRT and key file format or a PFX file format. You can also optionally provide a passphrase if the files are password-protected. +HTTP headers:: A set of key-value pairs sent as headers with the request. +Certificate authority:: +A certificate authority (CA) that the connector can trust, for example to sign and validate server certificates. +This option is available for all authentication types. +CA file::: +The certificate authority file. +Verification mode::: +Controls the certificate verification. ++ -- -xpack.actions.preconfigured: - my-webhook: - name: preconfigured-webhook-connector-type - actionTypeId: .webhook - config: - url: https://test.host - method: post - headers: - testheader: testvalue - secrets: - user: testuser - password: passwordkeystorevalue +* Use `full` to validate that the certificate has an issue date within the `not_before` and `not_after` dates, chains to a trusted certificate authority, and has a hostname or IP address that matches the names within the certificate. +* Use `certificate` to validate the certificate and verifies that it is signed by a trusted authority; this option does not check the certificate hostname. +* Use `none` to skip certificate validation. -- -Config defines information for the connector type. - -`url`:: A URL string that corresponds to *URL*. -`method`:: A string that corresponds to *Method*. -`headers`:: A record that corresponds to *Headers*. -`hasAuth`:: A boolean that corresponds to *Requires authentication*. If `true`, this connector will require values for `user` and `password` inside the secrets configuration. Defaults to `true`. - -Secrets defines sensitive information for the connector type. - -`user`:: A string that corresponds to *User*. Required if `hasAuth` is set to `true`. -`password`:: A string that corresponds to *Password*. Should be stored in the <>. Required if `hasAuth` is set to `true`. - [float] [[webhook-action-configuration]] === Test connectors @@ -75,6 +58,7 @@ as you're creating or editing the connector in {kib}. For example: [role="screenshot"] image::management/connectors/images/webhook-params-test.png[Webhook params test] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. Webhook actions have the following properties. diff --git a/docs/management/connectors/images/webhook-connector.png b/docs/management/connectors/images/webhook-connector.png index 6046572734afd..276fca05cee57 100644 Binary files a/docs/management/connectors/images/webhook-connector.png and b/docs/management/connectors/images/webhook-connector.png differ diff --git a/docs/management/connectors/images/webhook-params-test.png b/docs/management/connectors/images/webhook-params-test.png index 7b7007a72a0b6..4ae6660b85e26 100644 Binary files a/docs/management/connectors/images/webhook-params-test.png and b/docs/management/connectors/images/webhook-params-test.png differ diff --git a/docs/management/connectors/pre-configured-connectors.asciidoc b/docs/management/connectors/pre-configured-connectors.asciidoc index 43643f0f611ba..3584207a88364 100644 --- a/docs/management/connectors/pre-configured-connectors.asciidoc +++ b/docs/management/connectors/pre-configured-connectors.asciidoc @@ -80,3 +80,54 @@ 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 connectors + +The following example creates a <> with basic authentication: + +[source,text] +-- +xpack.actions.preconfigured: + my-webhook: + name: preconfigured-webhook-connector-type + actionTypeId: .webhook + config: + url: https://test.host <1> + method: post <2> + headers: <3> + testheader: testvalue + hasAuth: true <4> + secrets: + user: testuser <5> + password: passwordkeystorevalue <6> +-- + +<1> The web service request URL. If you are using the <> setting, make sure the hostname is added to the allowed hosts. +<2> The HTTP request method, either `post`(default) or `put`. +<3> A set of key-value pairs sent as headers with the request. +<4> If `true`, this connector will require values for `user` and `password` inside the secrets configuration. Defaults to `true`. +<5> A valid user name. Required if `hasAuth` is set to `true`. +<6> A valid password. Required if `hasAuth` is set to `true`. NOTE: This value should be stored in the <>. + +NOTE: SSL authentication is not supported in preconfigured webhook connectors. \ No newline at end of file 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/alerting/images/rule-types-es-query-conditions.png b/docs/user/alerting/images/rule-types-es-query-conditions.png index 1237c996f8822..cbe18e7bf0bdb 100644 Binary files a/docs/user/alerting/images/rule-types-es-query-conditions.png and b/docs/user/alerting/images/rule-types-es-query-conditions.png differ diff --git a/docs/user/alerting/images/rule-types-es-query-invalid.png b/docs/user/alerting/images/rule-types-es-query-invalid.png index ce8b8e92181a9..0d36e33741484 100644 Binary files a/docs/user/alerting/images/rule-types-es-query-invalid.png and b/docs/user/alerting/images/rule-types-es-query-invalid.png differ diff --git a/docs/user/alerting/images/rule-types-es-query-valid.png b/docs/user/alerting/images/rule-types-es-query-valid.png index 1894ad2b445f8..938662f49a063 100644 Binary files a/docs/user/alerting/images/rule-types-es-query-valid.png and b/docs/user/alerting/images/rule-types-es-query-valid.png differ diff --git a/docs/user/alerting/rule-types/es-query.asciidoc b/docs/user/alerting/rule-types/es-query.asciidoc index abe81f3e953ae..f8310eefa790f 100644 --- a/docs/user/alerting/rule-types/es-query.asciidoc +++ b/docs/user/alerting/rule-types/es-query.asciidoc @@ -23,7 +23,8 @@ Fill in the name and optional tags, then select Define properties to detect the condition. [role="screenshot"] -image::user/alerting/images/rule-types-es-query-conditions.png[Eight clauses define the condition to detect] +image::user/alerting/images/rule-types-es-query-conditions.png[Define the condition to detect] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. Define your query:: If you chose the query DSL option, you must specify indices to query and a time field that is used for the time window. You must then define a query in {es} query DSL. Only the `query`, `fields`, `_source` and `runtime_mappings` fields are used, other DSL fields are not considered. @@ -122,11 +123,13 @@ Use the *Test query* feature to verify that your query DSL is valid. + [role="screenshot"] image::user/alerting/images/rule-types-es-query-valid.png[Test {es} query returns number of matches when valid] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. * An error message is shown if the query is invalid. + [role="screenshot"] image::user/alerting/images/rule-types-es-query-invalid.png[Test {es} query shows error when invalid] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. [float] === Handling multiple matches of the same document diff --git a/docs/user/alerting/rule-types/geo-rule-types.asciidoc b/docs/user/alerting/rule-types/geo-rule-types.asciidoc index 837d7761a2e06..cfed5152e7657 100644 --- a/docs/user/alerting/rule-types/geo-rule-types.asciidoc +++ b/docs/user/alerting/rule-types/geo-rule-types.asciidoc @@ -10,7 +10,7 @@ In the event that an entity is contained within a boundary, an alert may be gene === Requirements To create a tracking containment rule, the following requirements must be present: -- *Tracks index or data view*: An index containing a `geo_point` field, `date` field, +- *Tracks index or data view*: An index containing a `geo_point` or `geo_shape` field, `date` field, and some form of entity identifier. An entity identifier is a `keyword` or `number` field that consistently identifies the entity to be tracked. The data in this index should be dynamically updating so that there are entity movements to alert upon. @@ -36,12 +36,7 @@ as well as two Kuery bars used to provide additional filtering context for each image::user/alerting/images/alert-types-tracking-containment-conditions.png[Define the condition to detect,width=75%] // NOTE: This is an autogenerated screenshot. Do not edit it directly. -Index (entity):: This clause requires an *index or data view*, a *time field* that will be used for the *time window*, and a *`geo_point` field* for tracking. -When entity:: This clause specifies which crossing option to track. The values -*Entered*, *Exited*, and *Crossed* can be selected to indicate which crossing conditions -should trigger a rule. *Entered* alerts on entry into a boundary, *Exited* alerts on exit -from a boundary, and *Crossed* alerts on all boundary crossings whether they be entrances -or exits. +Index (entity):: This clause requires an *index or data view*, a *time field* that will be used for the *time window*, and a *`geo_point` or `geo_shape` field* for tracking. Index (Boundary):: This clause requires an *index or data view*, a *`geo_shape` field* identifying boundaries, and an optional *Human-readable boundary name* for better alerting messages. diff --git a/docs/user/ml/images/ml-data-comparison.png b/docs/user/ml/images/ml-data-comparison.png new file mode 100644 index 0000000000000..428d625538603 Binary files /dev/null and b/docs/user/ml/images/ml-data-comparison.png differ diff --git a/docs/user/ml/index.asciidoc b/docs/user/ml/index.asciidoc index 59f7345923870..1d3bf33479d1b 100644 --- a/docs/user/ml/index.asciidoc +++ b/docs/user/ml/index.asciidoc @@ -31,6 +31,34 @@ privileges to use {ml-features}. Refer to NOTE: There are limitations in {ml-features} that affect {kib}. For more information, refer to {ml-docs}/ml-limitations.html[{ml-cap}]. +[discrete] +[[data-comparison-view]] +== Data comparison + +preview::[] + +You can find the data comparison view in **{ml-app}** > *{data-viz}* in {kib}. +The data comparison view shows you the differences in each field for two +different time ranges in a given {data-source}. The view helps you to visualize +the changes in your data over time and enables you to understand its behavior +better. + +[role="screenshot"] +image::user/ml/images/ml-data-comparison.png[Data comparison view for {kib} Sample Data Flights ] + +Select a {data-source} that you want to analyze, then select a time range for +the reference and the comparison data in the appearing histogram chart. You can +adjust the time range for both the reference and the comparison data by moving +the respective brushes. When you finished setting the time ranges, click +*Run analysis*. + +You can decide whether you want to see all the fields in the {data-source} or +only the ones that contains drifted data. The analysis results table displays +the fields, their types, if drift is detected, the p-value that indicates how +significant the detected change is, the reference and comparison distribution, +and the comparison chart. You can expand the results for a particular field by +clicking the arrow icon at the beginning of the field's row. + -- [[xpack-ml-anomalies]] @@ -123,11 +151,11 @@ advanced statistical methods to help you interpret your data and its behavior. preview::[] Log rate analysis is a feature that uses advanced statistical methods to -identify reasons for increases or decreases in log rates. It makes it easy to find and -investigate causes of unusual spikes or drops by using the analysis workflow view. -Examine the histogram chart of the log rates for a given {data-source}, and find -the reason behind a particular change possibly in millions of log events across -multiple fields and values. +identify reasons for increases or decreases in log rates. It makes it easy to +find and investigate causes of unusual spikes or drops by using the analysis +workflow view. Examine the histogram chart of the log rates for a given +{data-source}, and find the reason behind a particular change possibly in +millions of log events across multiple fields and values. You can find log rate analysis under **{ml-app}** > **AIOps Labs** where you can select the {data-source} or saved search that you want to analyze. 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/embeddable_examples/public/migrations/migration.7.3.0.ts b/examples/embeddable_examples/public/migrations/migration.7.3.0.ts deleted file mode 100644 index 79b61848a0166..0000000000000 --- a/examples/embeddable_examples/public/migrations/migration.7.3.0.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { MigrateFunction } from '@kbn/kibana-utils-plugin/common/persistable_state'; -import { EmbeddableInput } from '@kbn/embeddable-plugin/common'; -import { SimpleEmbeddableInput } from './migrations_embeddable_factory'; - -// before 7.3.0 this embeddable received a very simple input with a variable named `number` -// eslint-disable-next-line @typescript-eslint/naming-convention -type SimpleEmbeddableInput_pre7_3_0 = EmbeddableInput & { - number: number; -}; - -type SimpleEmbeddable730MigrateFn = MigrateFunction< - SimpleEmbeddableInput_pre7_3_0, - SimpleEmbeddableInput ->; - -// when migrating old state we'll need to set a default title, or we should make title optional in the new state -const defaultTitle = 'no title'; - -export const migration730: SimpleEmbeddable730MigrateFn = (state) => { - const newState: SimpleEmbeddableInput = { ...state, title: defaultTitle, value: state.number }; - return newState; -}; diff --git a/examples/embeddable_examples/public/migrations/migration_definitions.ts b/examples/embeddable_examples/public/migrations/migration_definitions.ts new file mode 100644 index 0000000000000..56e03bed313eb --- /dev/null +++ b/examples/embeddable_examples/public/migrations/migration_definitions.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { MigrateFunction } from '@kbn/kibana-utils-plugin/common/persistable_state'; +import { EmbeddableInput } from '@kbn/embeddable-plugin/common'; +import { SimpleEmbeddableInput } from './migrations_embeddable_factory'; + +// before 7.3.0 this embeddable received a very simple input with a variable named `number` +type SimpleEmbeddableInputV1 = EmbeddableInput & { + number: number; +}; + +type SimpleEmbeddable730MigrateFn = MigrateFunction; + +// when migrating old state we'll need to set a default title, or we should make title optional in the new state +const defaultTitle = 'no title'; + +export const migrateToVersion2: SimpleEmbeddable730MigrateFn = (state) => { + const newState: SimpleEmbeddableInput = { ...state, title: defaultTitle, value: state.number }; + return newState; +}; diff --git a/examples/embeddable_examples/public/migrations/migrations_embeddable_factory.ts b/examples/embeddable_examples/public/migrations/migrations_embeddable_factory.ts index 19efd95a12dde..fb96fbff77b35 100644 --- a/examples/embeddable_examples/public/migrations/migrations_embeddable_factory.ts +++ b/examples/embeddable_examples/public/migrations/migrations_embeddable_factory.ts @@ -15,7 +15,7 @@ import { EmbeddableFactory, } from '@kbn/embeddable-plugin/public'; import { SimpleEmbeddable } from './migrations_embeddable'; -import { migration730 } from './migration.7.3.0'; +import { migrateToVersion2 } from './migration_definitions'; export const SIMPLE_EMBEDDABLE = 'SIMPLE_EMBEDDABLE'; @@ -30,10 +30,11 @@ export class SimpleEmbeddableFactoryDefinition implements EmbeddableFactoryDefinition { public readonly type = SIMPLE_EMBEDDABLE; + public latestVersion = '2'; // we need to provide migration function every time we change the interface of our state public readonly migrations = { - '7.3.0': migration730, + '2': migrateToVersion2, }; public extract(state: EmbeddableStateWithType) { 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..a206560d48d80 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-1693558513", "forceAlignStackVersion": true, "allowSyncToPrerelease": true }, { "name": "elastic_agent", - "version": "1.11.2" + "version": "1.12.0" }, { "name": "endpoint", @@ -54,7 +54,7 @@ }, { "name": "synthetics", - "version": "1.0.4" + "version": "1.0.6" }, { "name": "security_detection_engine", diff --git a/package.json b/package.json index 19247a3a1a2fc..86071279c1ce4 100644 --- a/package.json +++ b/package.json @@ -84,12 +84,13 @@ "**/hoist-non-react-statics": "^3.3.2", "**/isomorphic-fetch/node-fetch": "^2.6.7", "**/remark-parse/trim": "1.0.1", - "**/typescript": "4.6.3", + "**/typescript": "4.7.4", "globby/fast-glob": "^3.2.11" }, "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", @@ -99,7 +100,7 @@ "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.9.1-canary.1", "@elastic/ems-client": "8.4.0", - "@elastic/eui": "87.1.0", + "@elastic/eui": "87.2.0", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", @@ -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,12 +607,14 @@ "@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", "@kbn/security-solution-serverless": "link:x-pack/plugins/security_solution_serverless", "@kbn/security-solution-side-nav": "link:x-pack/packages/security-solution/side_nav", "@kbn/security-solution-storybook-config": "link:x-pack/packages/security-solution/storybook/config", + "@kbn/security-solution-upselling": "link:x-pack/packages/security-solution/upselling", "@kbn/security-test-endpoints-plugin": "link:x-pack/test/security_functional/plugins/test_endpoints", "@kbn/securitysolution-autocomplete": "link:packages/kbn-securitysolution-autocomplete", "@kbn/securitysolution-data-table": "link:x-pack/packages/security-solution/data_table", @@ -736,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", @@ -805,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", @@ -894,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", @@ -1001,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", @@ -1362,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", @@ -1551,11 +1566,12 @@ "tree-kill": "^1.2.2", "ts-morph": "^13.0.2", "tsd": "^0.20.0", - "typescript": "4.6.3", + "typescript": "4.7.4", "url-loader": "^2.2.0", "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/fatal-errors/core-fatal-errors-browser-internal/src/__snapshots__/fatal_errors_screen.test.tsx.snap b/packages/core/fatal-errors/core-fatal-errors-browser-internal/src/__snapshots__/fatal_errors_screen.test.tsx.snap index 48caf45f0b0f1..962ba0ba9ba5b 100644 --- a/packages/core/fatal-errors/core-fatal-errors-browser-internal/src/__snapshots__/fatal_errors_screen.test.tsx.snap +++ b/packages/core/fatal-errors/core-fatal-errors-browser-internal/src/__snapshots__/fatal_errors_screen.test.tsx.snap @@ -2,6 +2,7 @@ exports[`FatalErrorsScreen rendering render matches snapshot 1`] = ` { public render() { return ( - + { - console.log(`Detected an unhandled Promise rejection.\n${e.reason}`); // eslint-disable-line no-console + const { message, stack } = getErrorInfo(e.reason); + // eslint-disable-next-line no-console + console.log(`Detected an unhandled Promise rejection.\n + Message: ${message}\n + Stack: ${stack}`); }); } } diff --git a/packages/core/http/core-http-router-server-internal/src/request.ts b/packages/core/http/core-http-router-server-internal/src/request.ts index 03348e1e9f577..05c35f4004efa 100644 --- a/packages/core/http/core-http-router-server-internal/src/request.ts +++ b/packages/core/http/core-http-router-server-internal/src/request.ts @@ -141,7 +141,7 @@ export class CoreKibanaRequest< public readonly rewrittenUrl?: URL; /** @internal */ - protected readonly [requestSymbol]: Request; + protected readonly [requestSymbol]!: Request; constructor( request: RawRequest, diff --git a/packages/core/http/core-http-router-server-internal/src/router.ts b/packages/core/http/core-http-router-server-internal/src/router.ts index 617c810109138..c265a7590d958 100644 --- a/packages/core/http/core-http-router-server-internal/src/router.ts +++ b/packages/core/http/core-http-router-server-internal/src/router.ts @@ -199,26 +199,38 @@ export class Router; -export function hasQueryVersion(request: KibanaRequest): request is KibanaRequestWithQueryVersion { +export function hasQueryVersion( + request: Mutable +): request is Mutable { return isObject(request.query) && ELASTIC_HTTP_VERSION_QUERY_PARAM in request.query; } export function removeQueryVersion(request: Mutable): void { 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/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap b/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap index cff710351cd74..2789cde01744d 100644 --- a/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap +++ b/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap @@ -291,8 +291,8 @@ exports[`#start() returns \`Context\` component 1`] = ` "euiRelativeTab.numberInputError": "Must be >= 0", "euiRelativeTab.numberInputLabel": "Time span amount", "euiRelativeTab.unitInputLabel": "Relative time span", - "euiResizableButton.horizontalResizerAriaLabel": "Press left or right to adjust panels size", - "euiResizableButton.verticalResizerAriaLabel": "Press up or down to adjust panels size", + "euiResizableButton.horizontalResizerAriaLabel": "Press the left or right arrow keys to adjust panels size", + "euiResizableButton.verticalResizerAriaLabel": "Press the up or down arrow keys to adjust panels size", "euiResizablePanel.toggleButtonAriaLabel": "Press to toggle this panel", "euiSaturation.ariaLabel": "HSV color mode saturation and value 2-axis slider", "euiSaturation.screenReaderInstructions": "Arrow keys to navigate the square color gradient. Coordinates will be used to calculate HSV color mode \\"saturation\\" and \\"value\\" numbers, in the range of 0 to 1. Left and right to change the saturation. Up and down change the value.", diff --git a/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx b/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx index c08df1f5a2bd8..bae77a2ac75de 100644 --- a/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx +++ b/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx @@ -1469,13 +1469,13 @@ export const getEuiContextMapping = (): EuiTokensObject => { 'euiResizableButton.horizontalResizerAriaLabel': i18n.translate( 'core.euiResizableButton.horizontalResizerAriaLabel', { - defaultMessage: 'Press left or right to adjust panels size', + defaultMessage: 'Press the left or right arrow keys to adjust panels size', } ), 'euiResizableButton.verticalResizerAriaLabel': i18n.translate( 'core.euiResizableButton.verticalResizerAriaLabel', { - defaultMessage: 'Press up or down to adjust panels size', + defaultMessage: 'Press the up or down arrow keys to adjust panels size', } ), 'euiResizablePanel.toggleButtonAriaLabel': i18n.translate( 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/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/rolling_tasks.ts b/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/rolling_tasks.ts index ef28ede1aeb29..15bae8901ddcb 100644 --- a/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/rolling_tasks.ts +++ b/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/rolling_tasks.ts @@ -7,8 +7,9 @@ */ import { join } from 'path'; -import { readdir, rename, unlink, access } from 'fs/promises'; +import { readdir, unlink, access } from 'fs/promises'; import { getFileNameMatcher, getRollingFileName } from './pattern_matcher'; +import { moveFile } from './utils'; export const shouldSkipRollout = async ({ logFilePath }: { logFilePath: string }) => { // in case of time-interval triggering policy, we can have an entire @@ -70,7 +71,7 @@ export const rollPreviousFilesInOrder = async ({ for (let i = filesToRoll.length - 1; i >= 0; i--) { const oldFileName = filesToRoll[i]; const newFileName = getRollingFileName(logFileBaseName, pattern, i + 2); - await rename(join(logFileFolder, oldFileName), join(logFileFolder, newFileName)); + await moveFile(join(logFileFolder, oldFileName), join(logFileFolder, newFileName)); } }; @@ -84,5 +85,5 @@ export const rollCurrentFile = async ({ pattern: string; }) => { const rolledBaseName = getRollingFileName(logFileBaseName, pattern, 1); - await rename(join(logFileFolder, logFileBaseName), join(logFileFolder, rolledBaseName)); + await moveFile(join(logFileFolder, logFileBaseName), join(logFileFolder, rolledBaseName)); }; diff --git a/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/utils.test.mocks.ts b/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/utils.test.mocks.ts new file mode 100644 index 0000000000000..d0bd7e91743e2 --- /dev/null +++ b/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/utils.test.mocks.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 const copyFileMock = jest.fn(); +export const renameMock = jest.fn(); +export const unlinkMock = jest.fn(); + +jest.doMock('fs/promises', () => { + const actual = jest.requireActual('fs/promises'); + return { + ...actual, + copyFile: copyFileMock, + rename: renameMock, + unlink: unlinkMock, + }; +}); diff --git a/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/utils.test.ts b/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/utils.test.ts new file mode 100644 index 0000000000000..17ed06763370a --- /dev/null +++ b/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/utils.test.ts @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { unlinkMock, renameMock, copyFileMock } from './utils.test.mocks'; +import { moveFile } from './utils'; + +describe('moveFile', () => { + beforeEach(() => { + unlinkMock.mockReset(); + renameMock.mockReset(); + copyFileMock.mockReset(); + }); + + it('only calls `rename` when call succeeds', async () => { + await moveFile('from', 'to'); + + expect(renameMock).toHaveBeenCalledTimes(1); + expect(renameMock).toHaveBeenCalledWith('from', 'to'); + + expect(copyFileMock).not.toHaveBeenCalled(); + expect(unlinkMock).not.toHaveBeenCalled(); + }); + + const createError = (code: string) => { + const err = new Error(code); + (err as any).code = code; + return err; + }; + + it('throws error if `rename` throws a non-EXDEV error', async () => { + renameMock.mockRejectedValue(createError('something')); + + await expect(moveFile('from', 'to')).rejects.toThrowError('something'); + + expect(renameMock).toHaveBeenCalledTimes(1); + expect(copyFileMock).not.toHaveBeenCalled(); + expect(unlinkMock).not.toHaveBeenCalled(); + }); + + it('fallback to copy+unlink when `rename` throws a EXDEV error', async () => { + renameMock.mockRejectedValue(createError('EXDEV')); + + await moveFile('from', 'to'); + + expect(renameMock).toHaveBeenCalledTimes(1); + expect(renameMock).toHaveBeenCalledWith('from', 'to'); + + expect(copyFileMock).toHaveBeenCalledTimes(1); + expect(copyFileMock).toHaveBeenCalledWith('from', 'to'); + + expect(unlinkMock).toHaveBeenCalledTimes(1); + expect(unlinkMock).toHaveBeenCalledWith('from'); + }); + + it('throws if copyFile call throws', async () => { + renameMock.mockRejectedValue(createError('EXDEV')); + copyFileMock.mockRejectedValue(createError('anything')); + + await expect(moveFile('from', 'to')).rejects.toThrowError('anything'); + + expect(renameMock).toHaveBeenCalledTimes(1); + + expect(copyFileMock).toHaveBeenCalledTimes(1); + + expect(unlinkMock).not.toHaveBeenCalled(); + }); + + it('throws if unlink call throws', async () => { + renameMock.mockRejectedValue(createError('EXDEV')); + unlinkMock.mockRejectedValue(createError('something-else')); + + await expect(moveFile('from', 'to')).rejects.toThrowError('something-else'); + + expect(renameMock).toHaveBeenCalledTimes(1); + + expect(copyFileMock).toHaveBeenCalledTimes(1); + + expect(unlinkMock).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/utils.ts b/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/utils.ts new file mode 100644 index 0000000000000..3cbe013a49282 --- /dev/null +++ b/packages/core/logging/core-logging-server-internal/src/appenders/rolling_file/strategies/numeric/utils.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { copyFile, rename, unlink } from 'fs/promises'; + +export const moveFile = async (oldPath: string, newPath: string): Promise => { + try { + await rename(oldPath, newPath); + } catch (err) { + // rename isn't supported on some file systems / volumes + // so we fallback to copy+delete + if (err.code === 'EXDEV') { + await copyFile(oldPath, newPath); + await unlink(oldPath); + } else { + throw err; + } + } +}; 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/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/index.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/index.ts new file mode 100644 index 0000000000000..e931a9c64c039 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/utils/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { 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 21c305d6f4216..d31407a937948 100644 --- a/packages/core/saved-objects/docs/openapi/bundled.json +++ b/packages/core/saved-objects/docs/openapi/bundled.json @@ -33,17 +33,1132 @@ } ], "paths": { + "/api/encrypted_saved_objects/_rotate_key": { + "post": { + "summary": "Rotate the encryption key for encrypted saved objects.", + "operationId": "rotateEncryptionKey", + "description": "Superuser role required.\n\nIf a saved object cannot be decrypted using the primary encryption key, then Kibana will attempt to decrypt it using the specified decryption-only keys. 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.\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": [ + { + "in": "query", + "name": "batch_size", + "schema": { + "type": "number", + "default": 10000 + }, + "required": false, + "description": "Specifies a maximum number of saved objects that Kibana can process in a single batch. Bulk key rotation is an iterative process since Kibana may not be able to fetch and process all required saved objects in one go and splits processing into consequent batches. By default, the batch size is 10000, which is also a maximum allowed value.\n" + }, + { + "in": "query", + "name": "type", + "schema": { + "type": "string" + }, + "required": false, + "description": "Limits encryption key rotation only to the saved objects with the specified type. By default, Kibana tries to rotate the encryption key for all saved object types that may contain encrypted attributes.\n" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "total": { + "type": "number", + "description": "Indicates the total number of all encrypted saved objects (optionally filtered by the requested `type`), regardless of the key Kibana used for encryption.\n" + }, + "successful": { + "type": "number", + "description": "Indicates the total number of all encrypted saved objects (optionally filtered by the requested `type`), regardless of the key Kibana used for encryption.\n\nNOTE: In most cases, `total` will be greater than `successful` even if `failed` is zero. The reason is that Kibana may not need or may not be able to rotate encryption keys for all encrypted saved objects.\n" + }, + "failed": { + "type": "number", + "description": "Indicates the number of the saved objects that were still encrypted with one of the old encryption keys that Kibana failed to re-encrypt with the primary key.\n" + } + } + }, + "examples": { + "rotateEncryptionKeyResponse": { + "$ref": "#/components/examples/key_rotation_response" + } + } + } + } + }, + "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": "This 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. NOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be exported.\n", + "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", + "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" + } + } + } + } + }, + "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/_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", + "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": { + "multipart/form-data": { + "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" + } + } + } + } + } + }, + "examples": { + "resolveImportErrorsRequest": { + "$ref": "#/components/examples/resolve_missing_reference_request" + } + } + } + } + }, + "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" + } + } + } + } + }, + "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" + } + } + } + }, + "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/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": { @@ -52,55 +1167,20 @@ "application/json": { "schema": { "type": "object", - "anyOf": [ - { - "required": [ - "type" - ] - }, - { - "required": [ - "objects" - ] - } + "required": [ + "attributes" ], "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" + "attributes": { + "$ref": "#/components/schemas/attributes" }, - "objects": { - "description": "A list of objects to export.", - "type": "array", - "items": { - "type": "object" - } + "initialNamespaces": { + "$ref": "#/components/schemas/initial_namespaces" }, - "type": { - "description": "The saved object types to include in the export.", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] + "references": { + "$ref": "#/components/schemas/initial_namespaces" } } - }, - "examples": { - "exportSavedObjectsRequest": { - "$ref": "#/components/examples/export_objects_request" - } } } } @@ -109,47 +1189,29 @@ "200": { "description": "Indicates a successful call.", "content": { - "multipart/form-data": { + "application/json": { "schema": { - "type": "string" - }, - "examples": { - "exportSavedObjectsResponse": { - "$ref": "#/components/examples/export_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/_import": { - "post": { - "summary": "Create sets of Kibana saved objects from a file created by the export API.", - "operationId": "importSavedObjects", - "description": "This 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. 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", + }, + "put": { + "summary": "Update the attributes for Kibana saved objects.", + "operationId": "updateSavedObject", + "deprecated": true, "tags": [ "saved objects" ], @@ -158,40 +1220,18 @@ "$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. Use this option only if you encounter issues with imported saved objects. NOTE: This option cannot be used with the `createNewCopies` option.\n" - }, - { - "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" + "$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" } ], "requestBody": { "required": true, "content": { - "multipart/form-data": { + "application/json": { "schema": { - "type": "object", - "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" + "type": "object" } } } @@ -202,36 +1242,63 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "errors": { - "type": "array", - "description": "Indicates the import was unsuccessful and specifies the objects that failed to import. One object may result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and conflict error.\n" - }, - "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." - }, - "successResults": { - "type": "array", - "items": { - "type": "object" - }, - "description": "Indicates the objects that are successfully imported, with any metadata if applicable. 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" - }, - "warnings": { - "type": "array" - } - } - }, - "examples": { - "importObjectsResponse": { - "$ref": "#/components/examples/import_objects_response" - } + "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.\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" } } } @@ -241,8 +1308,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": true + "$ref": "#/components/schemas/400_response" } } } @@ -273,40 +1339,75 @@ "name": "ApiKey" } }, - "parameters": { - "kbn_xsrf": { - "schema": { - "type": "string" - }, - "in": "header", - "name": "kbn-xsrf", - "description": "Cross-site request forgery protection", - "required": true - } - }, "examples": { + "key_rotation_response": { + "summary": "Encryption key rotation using default parameters.", + "value": { + "total": 1000, + "successful": 300, + "failed": 0 + } + }, "export_objects_request": { "summary": "Export a specific saved object.", "value": { "objects": [ { - "type": "index-pattern", - "id": "90943e30-9a47-11e8-b64d-95841ca0b247" + "type": "map", + "id": "de71f4f0-1902-11e9-919b-ffe5949a18d2" } ], - "includeReferencesDeep": false + "includeReferencesDeep": false, + "excludeExportDetails": true } }, "export_objects_response": { - "summary": "The export objects API response contains a JSON record for each exported object and an export result details record.", - "value": "{\"attributes\":{\"fieldFormatMap\":\"{\\\"hour_of_day\\\":{}}\",\"name\":\"Kibana Sample Data Logs\",\"runtimeFieldMap\":\"{\\\"hour_of_day\\\":{\\\"type\\\":\\\"long\\\",\\\"script\\\":{\\\"source\\\":\\\"emit(doc['timestamp'].value.getHour());\\\"}}}\",\"timeFieldName\":\"timestamp\",\"title\":\"kibana_sample_data_logs\"},\"coreMigrationVersion\":\"8.8.0\",\"created_at\":\"2023-07-25T19:36:36.695Z\",\"id\":\"90943e30-9a47-11e8-b64d-95841ca0b247\",\"managed\":false,\"references\":[],\"type\":\"index-pattern\",\"typeMigrationVersion\":\"8.0.0\",\"updated_at\":\"2023-07-25T19:36:36.695Z\",\"version\":\"WzM5LDJd\"}\n{\"excludedObjects\":[],\"excludedObjectsCount\":0,\"exportedCount\":1,\"missingRefCount\":0,\"missingReferences\":[]}\n" + "summary": "The export objects API response contains a JSON record for each exported object.", + "value": { + "attributes": { + "description": "", + "layerListJSON": "[{\"id\":\"0hmz5\",\"alpha\":1,\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true,\"lightModeDefault\":\"road_map_desaturated\"},\"visible\":true,\"style\":{},\"type\":\"EMS_VECTOR_TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"edh66\",\"label\":\"Total Requests by Destination\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.5,\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"world_countries\",\"tooltipProperties\":[\"name\",\"iso2\"]},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"__kbnjoin__count__673ff994-fc75-4c67-909b-69fcb0e1060e\",\"origin\":\"join\"},\"color\":\"Greys\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\",\"joins\":[{\"leftField\":\"iso2\",\"right\":{\"type\":\"ES_TERM_SOURCE\",\"id\":\"673ff994-fc75-4c67-909b-69fcb0e1060e\",\"indexPatternTitle\":\"kibana_sample_data_logs\",\"term\":\"geo.dest\",\"indexPatternRefName\":\"layer_1_join_0_index_pattern\",\"metrics\":[{\"type\":\"count\",\"label\":\"web logs count\"}],\"applyGlobalQuery\":true}}]},{\"id\":\"gaxya\",\"label\":\"Actual Requests\",\"minZoom\":9,\"maxZoom\":24,\"alpha\":1,\"sourceDescriptor\":{\"id\":\"b7486535-171b-4d3b-bb2e-33c1a0a2854c\",\"type\":\"ES_SEARCH\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[\"clientip\",\"timestamp\",\"host\",\"request\",\"response\",\"machine.os\",\"agent\",\"bytes\"],\"indexPatternRefName\":\"layer_2_source_index_pattern\",\"applyGlobalQuery\":true,\"scalingType\":\"LIMIT\"},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#2200ff\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":2}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"bytes\",\"origin\":\"source\"},\"minSize\":1,\"maxSize\":23,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\"},{\"id\":\"tfi3f\",\"label\":\"Total Requests and Bytes\",\"minZoom\":0,\"maxZoom\":9,\"alpha\":1,\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"resolution\":\"COARSE\",\"id\":\"8aaa65b5-a4e9-448b-9560-c98cb1c5ac5b\",\"geoField\":\"geo.coordinates\",\"requestType\":\"point\",\"metrics\":[{\"type\":\"count\",\"label\":\"web logs count\"},{\"type\":\"sum\",\"field\":\"bytes\"}],\"indexPatternRefName\":\"layer_3_source_index_pattern\",\"applyGlobalQuery\":true},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"sum_of_bytes\",\"origin\":\"source\"},\"minSize\":7,\"maxSize\":25,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"labelText\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"labelSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":12,\"maxSize\":24,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\"}]", + "mapStateJSON": "{\"zoom\":3.64,\"center\":{\"lon\":-88.92107,\"lat\":42.16337},\"timeFilters\":{\"from\":\"now-7d\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"settings\":{\"autoFitToDataBounds\":false}}", + "title": "[Logs] Total Requests and Bytes", + "uiStateJSON": "{\"isDarkMode\":false}" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2023-08-23T20:03:32.204Z", + "id": "de71f4f0-1902-11e9-919b-ffe5949a18d2", + "managed": false, + "references": [ + { + "id": "90943e30-9a47-11e8-b64d-95841ca0b247", + "name": "layer_1_join_0_index_pattern", + "type": "index-pattern" + }, + { + "id": "90943e30-9a47-11e8-b64d-95841ca0b247", + "name": "layer_2_source_index_pattern", + "type": "index-pattern" + }, + { + "id": "90943e30-9a47-11e8-b64d-95841ca0b247", + "name": "layer_3_source_index_pattern", + "type": "index-pattern" + } + ], + "type": "map", + "typeMigrationVersion": "8.4.0", + "updated_at": "2023-08-23T20:03:32.204Z", + "version": "WzEzLDFd" + } + }, + "import_objects_request": { + "value": { + "file": "file.ndjson" + } }, "import_objects_response": { "summary": "The import objects API response indicates a successful import and the objects are created. Since these objects are created as new copies, each entry in the successResults array includes a destinationId attribute.", "value": { "successCount": 1, "success": true, - "warnings": [], "successResults": [ { "type": "index-pattern", @@ -320,6 +1421,136 @@ } ] } + }, + "resolve_missing_reference_request": { + "value": { + "file": "file.ndjson", + "retries": [ + { + "type": "index-pattern", + "id": "my-pattern", + "overwrite": true + }, + { + "type": "visualization", + "id": "my-vis", + "overwrite": true, + "destinationId": "another-vis" + }, + { + "type": "canvas", + "id": "my-canvas", + "overwrite": true, + "destinationId": "yet-another-canvas" + }, + { + "type": "dashboard", + "id": "my-dashboard" + } + ] + } + }, + "resolve_missing_reference_response": { + "summary": "Resolve missing reference errors.", + "value": { + "success": true, + "successCount": 3, + "successResults": [ + { + "id": "my-vis", + "type": "visualization", + "meta": { + "icon": "visualizeApp", + "title": "Look at my visualization" + } + }, + { + "id": "my-search", + "type": "search", + "meta": { + "icon": "searchApp", + "title": "Look at my search" + } + }, + { + "id": "my-dashboard", + "type": "dashboard", + "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.\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": { + "type": "string" + }, + "in": "header", + "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 0facbd5446640..554895051768e 100644 --- a/packages/core/saved-objects/docs/openapi/bundled.yaml +++ b/packages/core/saved-objects/docs/openapi/bundled.yaml @@ -18,12 +18,274 @@ tags: - name: saved objects description: Manage Kibana saved objects, including dashboards, visualizations, and more. paths: + /api/encrypted_saved_objects/_rotate_key: + post: + summary: Rotate the encryption key for encrypted saved objects. + operationId: rotateEncryptionKey + description: | + Superuser role required. + + If a saved object cannot be decrypted using the primary encryption key, then Kibana will attempt to decrypt it using the specified decryption-only keys. 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. + + This 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. + tags: + - saved objects + parameters: + - in: query + name: batch_size + schema: + type: number + default: 10000 + required: false + description: | + Specifies a maximum number of saved objects that Kibana can process in a single batch. Bulk key rotation is an iterative process since Kibana may not be able to fetch and process all required saved objects in one go and splits processing into consequent batches. By default, the batch size is 10000, which is also a maximum allowed value. + - in: query + name: type + schema: + type: string + required: false + description: | + Limits encryption key rotation only to the saved objects with the specified type. By default, Kibana tries to rotate the encryption key for all saved object types that may contain encrypted attributes. + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + total: + type: number + description: | + Indicates the total number of all encrypted saved objects (optionally filtered by the requested `type`), regardless of the key Kibana used for encryption. + successful: + type: number + description: | + Indicates the total number of all encrypted saved objects (optionally filtered by the requested `type`), regardless of the key Kibana used for encryption. + + NOTE: In most cases, `total` will be greater than `successful` even if `failed` is zero. The reason is that Kibana may not need or may not be able to rotate encryption keys for all encrypted saved objects. + failed: + type: number + description: | + Indicates the number of the saved objects that were still encrypted with one of the old encryption keys that Kibana failed to re-encrypt with the primary key. + examples: + rotateEncryptionKeyResponse: + $ref: '#/components/examples/key_rotation_response' + '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. + 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. operationId: exportSavedObjects description: | - This 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. NOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be exported. + + You must include `type` or `objects` in the request body. + + NOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be exported. + + This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: @@ -34,11 +296,6 @@ paths: application/json: schema: type: object - anyOf: - - required: - - type - - required: - - objects properties: excludeExportDetails: description: Do not add export details entry at the end of the stream. @@ -53,7 +310,7 @@ paths: items: type: object type: - description: The saved object types to include in the export. + description: The saved object types to include in the export. Use `*` to export all the types. oneOf: - type: string - type: array @@ -66,19 +323,124 @@ paths: '200': description: Indicates a successful call. content: - multipart/form-data: + application/x-ndjson: schema: - type: string + 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. + 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: @@ -88,40 +450,47 @@ paths: summary: Create sets of Kibana saved objects from a file created by the export API. operationId: importSavedObjects description: | - This 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. 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. + Saved objects can be imported only into the same version, a newer minor on the same major, or the next major. Exported saved objects are not backwards compatible and cannot be imported into an older version of Kibana. + + This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: - $ref: '#/components/parameters/kbn_xsrf' - in: query - name: compatibilityMode + name: createNewCopies 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. + Creates copies of saved objects, regenerates each object ID, and resets the origin. When used, potential conflict errors are avoided. NOTE: This option cannot be used with the `overwrite` and `compatibilityMode` options. - in: query - name: createNewCopies + name: overwrite 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. + Overwrites saved objects when they already exist. When used, potential conflict errors are automatically resolved by overwriting the destination object. NOTE: This option cannot be used with the `createNewCopies` option. - in: query - name: overwrite + name: compatibilityMode 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. + Applies various adjustments to the saved objects that are being imported to maintain compatibility between different Kibana versions. Use this option only if you encounter issues with imported saved objects. NOTE: This option cannot be used with the `createNewCopies` option. requestBody: required: true content: multipart/form-data: schema: type: object - 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. + properties: + file: + description: | + A file exported using the export API. NOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be included in this file. Similarly, the `savedObjects.maxImportPayloadBytes` setting limits the overall size of the file that can be imported. + examples: + importObjectsRequest: + $ref: '#/components/examples/import_objects_request' responses: '200': description: Indicates a successful call. @@ -130,10 +499,6 @@ paths: schema: type: object properties: - errors: - type: array - description: | - Indicates the import was unsuccessful and specifies the objects that failed to import. One object may result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and conflict error. success: type: boolean description: | @@ -141,24 +506,337 @@ paths: successCount: type: integer description: Indicates the number of successfully imported records. - successResults: + errors: type: array items: type: object description: | - Indicates the objects that are successfully imported, with any metadata if applicable. 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. - warnings: + Indicates the import was unsuccessful and specifies the objects that failed to import. + + NOTE: One object may result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and conflict error. + successResults: type: array + items: + type: object + description: | + Indicates the objects that are successfully imported, with any metadata if applicable. + + NOTE: Objects are created only when all resolvable errors are addressed, including conflicts and missing references. If objects are created as new copies, each entry in the `successResults` array includes a `destinationId` attribute. examples: importObjectsResponse: $ref: '#/components/examples/import_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/_resolve_import_errors: + post: + summary: Resolve errors from the Import objects API. + operationId: resolveImportErrors + description: | + To resolve errors, you can: + + * Retry certain saved objects + * Overwrite specific saved objects + * Change references to different saved objects + + This 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. + 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. + - 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. + requestBody: + required: true + content: + multipart/form-data: + 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 + examples: + resolveImportErrorsRequest: + $ref: '#/components/examples/resolve_missing_reference_request' + responses: + '200': + description: Indicates a successful call. content: 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. + successCount: + type: number + description: | + Indicates the number of successfully resolved records. + errors: + type: array + description: | + Specifies the objects that failed to resolve. + + NOTE: One object can result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and a `conflict` error. + items: + type: object + successResults: + type: array + description: | + Indicates the objects that are successfully imported, with any metadata if applicable. + + NOTE: Objects are only created when all resolvable errors are addressed, including conflict and missing references. + items: + type: object + examples: + resolveImportErrorsResponse: + $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 + '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: @@ -172,33 +850,56 @@ components: type: apiKey in: header name: ApiKey - parameters: - kbn_xsrf: - schema: - type: string - in: header - name: kbn-xsrf - description: Cross-site request forgery protection - required: true examples: + key_rotation_response: + summary: Encryption key rotation using default parameters. + value: + total: 1000 + successful: 300 + failed: 0 export_objects_request: summary: Export a specific saved object. value: objects: - - type: index-pattern - id: 90943e30-9a47-11e8-b64d-95841ca0b247 + - type: map + id: de71f4f0-1902-11e9-919b-ffe5949a18d2 includeReferencesDeep: false + excludeExportDetails: true export_objects_response: - summary: The export objects API response contains a JSON record for each exported object and an export result details record. - value: | - {"attributes":{"fieldFormatMap":"{\"hour_of_day\":{}}","name":"Kibana Sample Data Logs","runtimeFieldMap":"{\"hour_of_day\":{\"type\":\"long\",\"script\":{\"source\":\"emit(doc['timestamp'].value.getHour());\"}}}","timeFieldName":"timestamp","title":"kibana_sample_data_logs"},"coreMigrationVersion":"8.8.0","created_at":"2023-07-25T19:36:36.695Z","id":"90943e30-9a47-11e8-b64d-95841ca0b247","managed":false,"references":[],"type":"index-pattern","typeMigrationVersion":"8.0.0","updated_at":"2023-07-25T19:36:36.695Z","version":"WzM5LDJd"} - {"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":1,"missingRefCount":0,"missingReferences":[]} + summary: The export objects API response contains a JSON record for each exported object. + value: + attributes: + description: '' + layerListJSON: '[{"id":"0hmz5","alpha":1,"sourceDescriptor":{"type":"EMS_TMS","isAutoSelect":true,"lightModeDefault":"road_map_desaturated"},"visible":true,"style":{},"type":"EMS_VECTOR_TILE","minZoom":0,"maxZoom":24},{"id":"edh66","label":"Total Requests by Destination","minZoom":0,"maxZoom":24,"alpha":0.5,"sourceDescriptor":{"type":"EMS_FILE","id":"world_countries","tooltipProperties":["name","iso2"]},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"__kbnjoin__count__673ff994-fc75-4c67-909b-69fcb0e1060e","origin":"join"},"color":"Greys","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#FFFFFF"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"STATIC","options":{"size":10}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"GEOJSON_VECTOR","joins":[{"leftField":"iso2","right":{"type":"ES_TERM_SOURCE","id":"673ff994-fc75-4c67-909b-69fcb0e1060e","indexPatternTitle":"kibana_sample_data_logs","term":"geo.dest","indexPatternRefName":"layer_1_join_0_index_pattern","metrics":[{"type":"count","label":"web logs count"}],"applyGlobalQuery":true}}]},{"id":"gaxya","label":"Actual Requests","minZoom":9,"maxZoom":24,"alpha":1,"sourceDescriptor":{"id":"b7486535-171b-4d3b-bb2e-33c1a0a2854c","type":"ES_SEARCH","geoField":"geo.coordinates","limit":2048,"filterByMapBounds":true,"tooltipProperties":["clientip","timestamp","host","request","response","machine.os","agent","bytes"],"indexPatternRefName":"layer_2_source_index_pattern","applyGlobalQuery":true,"scalingType":"LIMIT"},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"STATIC","options":{"color":"#2200ff"}},"lineColor":{"type":"STATIC","options":{"color":"#FFFFFF"}},"lineWidth":{"type":"STATIC","options":{"size":2}},"iconSize":{"type":"DYNAMIC","options":{"field":{"name":"bytes","origin":"source"},"minSize":1,"maxSize":23,"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"GEOJSON_VECTOR"},{"id":"tfi3f","label":"Total Requests and Bytes","minZoom":0,"maxZoom":9,"alpha":1,"sourceDescriptor":{"type":"ES_GEO_GRID","resolution":"COARSE","id":"8aaa65b5-a4e9-448b-9560-c98cb1c5ac5b","geoField":"geo.coordinates","requestType":"point","metrics":[{"type":"count","label":"web logs count"},{"type":"sum","field":"bytes"}],"indexPatternRefName":"layer_3_source_index_pattern","applyGlobalQuery":true},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"doc_count","origin":"source"},"color":"Blues","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#cccccc"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"DYNAMIC","options":{"field":{"name":"sum_of_bytes","origin":"source"},"minSize":7,"maxSize":25,"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"labelText":{"type":"DYNAMIC","options":{"field":{"name":"doc_count","origin":"source"},"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"labelSize":{"type":"DYNAMIC","options":{"field":{"name":"doc_count","origin":"source"},"minSize":12,"maxSize":24,"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"GEOJSON_VECTOR"}]' + mapStateJSON: '{"zoom":3.64,"center":{"lon":-88.92107,"lat":42.16337},"timeFilters":{"from":"now-7d","to":"now"},"refreshConfig":{"isPaused":true,"interval":0},"query":{"language":"kuery","query":""},"settings":{"autoFitToDataBounds":false}}' + title: '[Logs] Total Requests and Bytes' + uiStateJSON: '{"isDarkMode":false}' + coreMigrationVersion: 8.8.0 + created_at: '2023-08-23T20:03:32.204Z' + id: de71f4f0-1902-11e9-919b-ffe5949a18d2 + managed: false + references: + - id: 90943e30-9a47-11e8-b64d-95841ca0b247 + name: layer_1_join_0_index_pattern + type: index-pattern + - id: 90943e30-9a47-11e8-b64d-95841ca0b247 + name: layer_2_source_index_pattern + type: index-pattern + - id: 90943e30-9a47-11e8-b64d-95841ca0b247 + name: layer_3_source_index_pattern + type: index-pattern + type: map + typeMigrationVersion: 8.4.0 + updated_at: '2023-08-23T20:03:32.204Z' + version: WzEzLDFd + import_objects_request: + value: + file: file.ndjson import_objects_response: summary: The import objects API response indicates a successful import and the objects are created. Since these objects are created as new copies, each entry in the successResults array includes a destinationId attribute. value: successCount: 1 success: true - warnings: [] successResults: - type: index-pattern id: 90943e30-9a47-11e8-b64d-95841ca0b247 @@ -207,3 +908,94 @@ components: icon: indexPatternApp managed: false destinationId: 82d2760c-468f-49cf-83aa-b9a35b6a8943 + resolve_missing_reference_request: + value: + file: file.ndjson + retries: + - type: index-pattern + id: my-pattern + overwrite: true + - type: visualization + id: my-vis + overwrite: true + destinationId: another-vis + - type: canvas + id: my-canvas + overwrite: true + destinationId: yet-another-canvas + - type: dashboard + id: my-dashboard + resolve_missing_reference_response: + summary: Resolve missing reference errors. + value: + success: true + successCount: 3 + successResults: + - id: my-vis + type: visualization + meta: + icon: visualizeApp + title: Look at my visualization + - id: my-search + type: search + meta: + icon: searchApp + title: Look at my search + - id: my-dashboard + type: dashboard + 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: + type: string + in: header + 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/examples/export_objects_request.yaml b/packages/core/saved-objects/docs/openapi/components/examples/export_objects_request.yaml index 065e956d0f6ab..d841423a82a30 100644 --- a/packages/core/saved-objects/docs/openapi/components/examples/export_objects_request.yaml +++ b/packages/core/saved-objects/docs/openapi/components/examples/export_objects_request.yaml @@ -3,9 +3,10 @@ value: { "objects": [ { - "type": "index-pattern", - "id": "90943e30-9a47-11e8-b64d-95841ca0b247" + "type": "map", + "id": "de71f4f0-1902-11e9-919b-ffe5949a18d2" } ], - "includeReferencesDeep": false + "includeReferencesDeep": false, + "excludeExportDetails": true } \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/components/examples/export_objects_response.yaml b/packages/core/saved-objects/docs/openapi/components/examples/export_objects_response.yaml index f6eb12f671b20..001c7e192324f 100644 --- a/packages/core/saved-objects/docs/openapi/components/examples/export_objects_response.yaml +++ b/packages/core/saved-objects/docs/openapi/components/examples/export_objects_response.yaml @@ -1,4 +1,3 @@ -summary: The export objects API response contains a JSON record for each exported object and an export result details record. -value: | - {"attributes":{"fieldFormatMap":"{\"hour_of_day\":{}}","name":"Kibana Sample Data Logs","runtimeFieldMap":"{\"hour_of_day\":{\"type\":\"long\",\"script\":{\"source\":\"emit(doc['timestamp'].value.getHour());\"}}}","timeFieldName":"timestamp","title":"kibana_sample_data_logs"},"coreMigrationVersion":"8.8.0","created_at":"2023-07-25T19:36:36.695Z","id":"90943e30-9a47-11e8-b64d-95841ca0b247","managed":false,"references":[],"type":"index-pattern","typeMigrationVersion":"8.0.0","updated_at":"2023-07-25T19:36:36.695Z","version":"WzM5LDJd"} - {"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":1,"missingRefCount":0,"missingReferences":[]} \ No newline at end of file +summary: The export objects API response contains a JSON record for each exported object. +value: + {"attributes":{"description":"","layerListJSON":"[{\"id\":\"0hmz5\",\"alpha\":1,\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true,\"lightModeDefault\":\"road_map_desaturated\"},\"visible\":true,\"style\":{},\"type\":\"EMS_VECTOR_TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"edh66\",\"label\":\"Total Requests by Destination\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.5,\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"world_countries\",\"tooltipProperties\":[\"name\",\"iso2\"]},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"__kbnjoin__count__673ff994-fc75-4c67-909b-69fcb0e1060e\",\"origin\":\"join\"},\"color\":\"Greys\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\",\"joins\":[{\"leftField\":\"iso2\",\"right\":{\"type\":\"ES_TERM_SOURCE\",\"id\":\"673ff994-fc75-4c67-909b-69fcb0e1060e\",\"indexPatternTitle\":\"kibana_sample_data_logs\",\"term\":\"geo.dest\",\"indexPatternRefName\":\"layer_1_join_0_index_pattern\",\"metrics\":[{\"type\":\"count\",\"label\":\"web logs count\"}],\"applyGlobalQuery\":true}}]},{\"id\":\"gaxya\",\"label\":\"Actual Requests\",\"minZoom\":9,\"maxZoom\":24,\"alpha\":1,\"sourceDescriptor\":{\"id\":\"b7486535-171b-4d3b-bb2e-33c1a0a2854c\",\"type\":\"ES_SEARCH\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[\"clientip\",\"timestamp\",\"host\",\"request\",\"response\",\"machine.os\",\"agent\",\"bytes\"],\"indexPatternRefName\":\"layer_2_source_index_pattern\",\"applyGlobalQuery\":true,\"scalingType\":\"LIMIT\"},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#2200ff\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":2}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"bytes\",\"origin\":\"source\"},\"minSize\":1,\"maxSize\":23,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\"},{\"id\":\"tfi3f\",\"label\":\"Total Requests and Bytes\",\"minZoom\":0,\"maxZoom\":9,\"alpha\":1,\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"resolution\":\"COARSE\",\"id\":\"8aaa65b5-a4e9-448b-9560-c98cb1c5ac5b\",\"geoField\":\"geo.coordinates\",\"requestType\":\"point\",\"metrics\":[{\"type\":\"count\",\"label\":\"web logs count\"},{\"type\":\"sum\",\"field\":\"bytes\"}],\"indexPatternRefName\":\"layer_3_source_index_pattern\",\"applyGlobalQuery\":true},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"sum_of_bytes\",\"origin\":\"source\"},\"minSize\":7,\"maxSize\":25,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"labelText\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"labelSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":12,\"maxSize\":24,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\"}]","mapStateJSON":"{\"zoom\":3.64,\"center\":{\"lon\":-88.92107,\"lat\":42.16337},\"timeFilters\":{\"from\":\"now-7d\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"settings\":{\"autoFitToDataBounds\":false}}","title":"[Logs] Total Requests and Bytes","uiStateJSON":"{\"isDarkMode\":false}"},"coreMigrationVersion":"8.8.0","created_at":"2023-08-23T20:03:32.204Z","id":"de71f4f0-1902-11e9-919b-ffe5949a18d2","managed":false,"references":[{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"layer_1_join_0_index_pattern","type":"index-pattern"},{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"layer_2_source_index_pattern","type":"index-pattern"},{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"layer_3_source_index_pattern","type":"index-pattern"}],"type":"map","typeMigrationVersion":"8.4.0","updated_at":"2023-08-23T20:03:32.204Z","version":"WzEzLDFd"} \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/components/examples/import_objects_request.yaml b/packages/core/saved-objects/docs/openapi/components/examples/import_objects_request.yaml new file mode 100644 index 0000000000000..9378436aafbc5 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/examples/import_objects_request.yaml @@ -0,0 +1,2 @@ +value: + file: file.ndjson \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/components/examples/import_objects_response.yaml b/packages/core/saved-objects/docs/openapi/components/examples/import_objects_response.yaml index a19cf00a9bb97..a12799dd6b17a 100644 --- a/packages/core/saved-objects/docs/openapi/components/examples/import_objects_response.yaml +++ b/packages/core/saved-objects/docs/openapi/components/examples/import_objects_response.yaml @@ -3,7 +3,6 @@ value: { "successCount":1, "success":true, - "warnings":[], "successResults":[ { "type":"index-pattern", diff --git a/packages/core/saved-objects/docs/openapi/components/examples/key_rotation_response.yaml b/packages/core/saved-objects/docs/openapi/components/examples/key_rotation_response.yaml new file mode 100644 index 0000000000000..11527996dfd44 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/examples/key_rotation_response.yaml @@ -0,0 +1,7 @@ +summary: Encryption key rotation using default parameters. +value: + { + "total": 1000, + "successful": 300, + "failed": 0 + } \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/components/examples/resolve_missing_reference_request.yaml b/packages/core/saved-objects/docs/openapi/components/examples/resolve_missing_reference_request.yaml new file mode 100644 index 0000000000000..26897d5fc027e --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/examples/resolve_missing_reference_request.yaml @@ -0,0 +1,16 @@ +value: + file: file.ndjson + retries: + - type: index-pattern + id: my-pattern + overwrite: true + - type: visualization + id: my-vis + overwrite: true + destinationId: another-vis + - type: canvas + id: my-canvas + overwrite: true + destinationId: yet-another-canvas + - type: dashboard + id: my-dashboard \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/components/examples/resolve_missing_reference_response.yaml b/packages/core/saved-objects/docs/openapi/components/examples/resolve_missing_reference_response.yaml new file mode 100644 index 0000000000000..065b820ce3ab2 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/components/examples/resolve_missing_reference_response.yaml @@ -0,0 +1,20 @@ +summary: Resolve missing reference errors. +value: + success: true + successCount: 3 + successResults: + - id: my-vis + type: visualization + meta: + icon: visualizeApp + title: Look at my visualization + - id: my-search + type: search + meta: + icon: searchApp + title: Look at my search + - id: my-dashboard + type: dashboard + meta: + icon: dashboardApp + title: Look at my dashboard \ No newline at end of file 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 a76f7880822fe..f20b8204b4bd4 100644 --- a/packages/core/saved-objects/docs/openapi/entrypoint.yaml +++ b/packages/core/saved-objects/docs/openapi/entrypoint.yaml @@ -16,32 +16,32 @@ servers: description: local 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/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/_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/_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' components: securitySchemes: basicAuth: @@ -53,4 +53,4 @@ components: name: ApiKey security: - basicAuth: [] - - apiKeyAuth: [] + - apiKeyAuth: [] \ No newline at end of file diff --git a/packages/core/saved-objects/docs/openapi/paths/README.md b/packages/core/saved-objects/docs/openapi/paths/README.md index b7818c8474fc8..8b2289c89cbe6 100644 --- a/packages/core/saved-objects/docs/openapi/paths/README.md +++ b/packages/core/saved-objects/docs/openapi/paths/README.md @@ -7,4 +7,4 @@ These files currently use the following conventions: * path separator token (e.g. `@`) is included in the file name * path parameter (e.g. `{example}`) is included in the file name -* there is one file per path; each file can contain multiple operations +* there is one file per path; each file can contain multiple operations \ No newline at end of file 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 new file mode 100644 index 0000000000000..94ab9cb3f6286 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@encrypted_saved_objects@_rotate_key.yaml @@ -0,0 +1,68 @@ +post: + summary: Rotate the encryption key for encrypted saved objects. + operationId: rotateEncryptionKey + description: | + Superuser role required. + + If a saved object cannot be decrypted using the primary encryption key, then Kibana will attempt to decrypt it using the specified decryption-only keys. 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. + + This 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. + tags: + - saved objects + parameters: + - in: query + name: batch_size + schema: + type: number + default: 10000 + required: false + description: | + Specifies a maximum number of saved objects that Kibana can process in a single batch. Bulk key rotation is an iterative process since Kibana may not be able to fetch and process all required saved objects in one go and splits processing into consequent batches. By default, the batch size is 10000, which is also a maximum allowed value. + - in: query + name: type + schema: + type: string + required: false + description: | + Limits encryption key rotation only to the saved objects with the specified type. By default, Kibana tries to rotate the encryption key for all saved object types that may contain encrypted attributes. + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + total: + type: number + description: | + Indicates the total number of all encrypted saved objects (optionally filtered by the requested `type`), regardless of the key Kibana used for encryption. + successful: + type: number + description: | + Indicates the total number of all encrypted saved objects (optionally filtered by the requested `type`), regardless of the key Kibana used for encryption. + + NOTE: In most cases, `total` will be greater than `successful` even if `failed` is zero. The reason is that Kibana may not need or may not be able to rotate encryption keys for all encrypted saved objects. + failed: + type: number + description: | + Indicates the number of the saved objects that were still encrypted with one of the old encryption keys that Kibana failed to re-encrypt with the primary key. + examples: + rotateEncryptionKeyResponse: + $ref: '../components/examples/key_rotation_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + '429': + description: Already in progress. + content: + application/json: + schema: + type: object + 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_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 2c3cb60aff742..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 @@ -1,9 +1,13 @@ post: summary: Retrieve sets of saved objects that you want to import into Kibana. operationId: exportSavedObjects - description: > - This 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. + description: | + + You must include `type` or `objects` in the request body. + NOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be exported. + + This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: @@ -14,9 +18,6 @@ post: application/json: schema: type: object - anyOf: - - required: [type] - - required: [objects] properties: excludeExportDetails: description: Do not add export details entry at the end of the stream. @@ -31,7 +32,7 @@ post: items: type: object type: - description: The saved object types to include in the export. + description: The saved object types to include in the export. Use `*` to export all the types. oneOf: - type: string - type: array @@ -44,9 +45,10 @@ post: '200': description: Indicates a successful call. content: - multipart/form-data: + application/x-ndjson: schema: - type: string + type: object + additionalProperties: true examples: exportSavedObjectsResponse: $ref: '../components/examples/export_objects_response.yaml' @@ -55,9 +57,8 @@ post: content: application/json: schema: - type: object - additionalProperties: true + $ref: '../components/schemas/400_response.yaml' servers: - - url: https://localhost:5601 + - url: https://localhost:5601 servers: - - url: https://localhost:5601 \ No newline at end of file + - url: https://localhost:5601 \ No newline at end of file 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 a6c21a5d9551b..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 @@ -1,84 +1,79 @@ post: summary: Create sets of Kibana saved objects from a file created by the export API. operationId: importSavedObjects - description: > + 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. + This 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. - 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. tags: - saved objects parameters: - $ref: '../components/headers/kbn_xsrf.yaml' - in: query - name: compatibilityMode + name: createNewCopies 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. + description: | + Creates copies of saved objects, regenerates each object ID, and resets the origin. When used, potential conflict errors are avoided. NOTE: This option cannot be used with the `overwrite` and `compatibilityMode` options. - in: query - name: createNewCopies + name: overwrite 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. + description: | + Overwrites saved objects when they already exist. When used, potential conflict errors are automatically resolved by overwriting the destination object. NOTE: This option cannot be used with the `createNewCopies` option. - in: query - name: overwrite + name: compatibilityMode 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. + description: | + Applies various adjustments to the saved objects that are being imported to maintain compatibility between different Kibana versions. Use this option only if you encounter issues with imported saved objects. NOTE: This option cannot be used with the `createNewCopies` option. requestBody: required: true content: multipart/form-data: schema: type: object - 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. + properties: + file: + description: | + A file exported using the export API. NOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be included in this file. Similarly, the `savedObjects.maxImportPayloadBytes` setting limits the overall size of the file that can be imported. + examples: + importObjectsRequest: + $ref: '../components/examples/import_objects_request.yaml' responses: '200': description: Indicates a successful call. content: - application/json: + application/json: schema: type: object properties: - errors: - type: array - description: > - Indicates the import was unsuccessful and specifies the objects that failed to import. - One object may result in multiple errors, which requires separate steps to resolve. - For instance, a `missing_references` error and conflict error. 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. + description: | + Indicates when the import was successfully completed. When set to false, some objects may not have been created. For additional information, refer to the `errors` and `successResults` properties. successCount: type: integer description: Indicates the number of successfully imported records. + errors: + type: array + items: + type: object + description: | + Indicates the import was unsuccessful and specifies the objects that failed to import. + + NOTE: One object may result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and conflict error. successResults: type: array items: type: object - description: > + description: | Indicates the objects that are successfully imported, with any metadata if applicable. - 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. - warnings: - type: array + + NOTE: Objects are created only when all resolvable errors are addressed, including conflicts and missing references. If objects are created as new copies, each entry in the `successResults` array includes a `destinationId` attribute. examples: importObjectsResponse: $ref: '../components/examples/import_objects_response.yaml' @@ -87,9 +82,8 @@ post: content: application/json: schema: - type: object - additionalProperties: true + $ref: '../components/schemas/400_response.yaml' servers: - - url: https://localhost:5601 + - url: https://localhost:5601 servers: - - url: https://localhost:5601 \ No newline at end of file +- url: https://localhost:5601 \ No newline at end of file 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 new file mode 100644 index 0000000000000..6c49f1925e3e5 --- /dev/null +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_resolve_import_errors.yaml @@ -0,0 +1,126 @@ +post: + summary: Resolve errors from the Import objects API. + operationId: resolveImportErrors + description: | + To resolve errors, you can: + + * Retry certain saved objects + * Overwrite specific saved objects + * Change references to different saved objects + + This 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. + tags: + - saved objects + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - 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. + - 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. + requestBody: + required: true + content: + multipart/form-data: + 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 + examples: + resolveImportErrorsRequest: + $ref: '../components/examples/resolve_missing_reference_request.yaml' + 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. + successCount: + type: number + description: | + Indicates the number of successfully resolved records. + errors: + type: array + description: | + Specifies the objects that failed to resolve. + + NOTE: One object can result in multiple errors, which requires separate steps to resolve. For instance, a `missing_references` error and a `conflict` error. + items: + type: object + successResults: + type: array + description: | + Indicates the objects that are successfully imported, with any metadata if applicable. + + NOTE: Objects are only created when all resolvable errors are addressed, including conflict and missing references. + items: + type: object + examples: + resolveImportErrorsResponse: + $ref: '../components/examples/resolve_missing_reference_response.yaml' + '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@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/status/core-status-server-internal/src/routes/status.ts b/packages/core/status/core-status-server-internal/src/routes/status.ts index 403686bdf2688..e06d667b4c78b 100644 --- a/packages/core/status/core-status-server-internal/src/routes/status.ts +++ b/packages/core/status/core-status-server-internal/src/routes/status.ts @@ -82,7 +82,10 @@ export const registerStatusRoute = ({ path: '/api/status', options: { authRequired: 'optional', - tags: ['api'], // ensures that unauthenticated calls receive a 401 rather than a 302 redirect to login page + // The `api` tag ensures that unauthenticated calls receive a 401 rather than a 302 redirect to login page. + // The `security:acceptJWT` tag allows route to be accessed with JWT credentials. It points to + // ROUTE_TAG_ACCEPT_JWT from '@kbn/security-plugin/server' that cannot be imported here directly. + tags: ['api', 'security:acceptJWT'], access: 'public', // needs to be public to allow access from "system" users like k8s readiness probes. }, validate: { diff --git a/packages/core/test-helpers/core-test-helpers-kbn-server/index.ts b/packages/core/test-helpers/core-test-helpers-kbn-server/index.ts index a9a992daae212..eac1a3472ebb4 100644 --- a/packages/core/test-helpers/core-test-helpers-kbn-server/index.ts +++ b/packages/core/test-helpers/core-test-helpers-kbn-server/index.ts @@ -12,7 +12,15 @@ export { createRoot, createRootWithCorePlugins, createTestServers, + createTestServerlessInstances, request, } from './src'; -export type { HttpMethod, TestElasticsearchUtils, TestKibanaUtils, TestUtils } from './src'; +export type { + HttpMethod, + TestElasticsearchUtils, + TestKibanaUtils, + TestUtils, + TestServerlessESUtils, + TestServerlessKibanaUtils, +} from './src'; 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 new file mode 100644 index 0000000000000..3e12b16832714 --- /dev/null +++ b/packages/core/test-helpers/core-test-helpers-kbn-server/src/create_serverless_root.ts @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Path from 'path'; +import { defaultsDeep } from 'lodash'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; +import { Cluster } from '@kbn/es'; +import { REPO_ROOT } from '@kbn/repo-info'; +import { ToolingLog } from '@kbn/tooling-log'; +import { CliArgs } from '@kbn/config'; +import { createRoot, type TestElasticsearchUtils, type TestKibanaUtils } from './create_root'; + +export type TestServerlessESUtils = Pick & { + getClient: () => Client; +}; +export type TestServerlessKibanaUtils = TestKibanaUtils; + +export interface TestServerlessUtils { + startES: () => Promise; + startKibana: (abortSignal?: AbortSignal) => Promise; +} + +/** + * See docs in {@link TestUtils}. This function provides the same utilities but + * configured for serverless. + * + * @note requires a Docker installation to be running + */ +export function createTestServerlessInstances({ + adjustTimeout, +}: { + adjustTimeout: (timeout: number) => void; +}): TestServerlessUtils { + const esUtils = createServerlessES(); + const kbUtils = createServerlessKibana(); + adjustTimeout?.(120_000); + return { + startES: async () => { + const { stop, getClient } = await esUtils.start(); + return { + es: esUtils.es, + getClient, + stop, + }; + }, + startKibana: async (abortSignal) => { + abortSignal?.addEventListener('abort', async () => await kbUtils.shutdown()); + await kbUtils.preboot(); + const coreSetup = await kbUtils.setup(); + const coreStart = await kbUtils.start(); + return { + root: kbUtils, + coreSetup, + coreStart, + stop: kbUtils.shutdown.bind(kbUtils), + }; + }, + }; +} + +const ES_BASE_PATH_DIR = Path.join(REPO_ROOT, '.es/es_test_serverless'); +function createServerlessES() { + const log = new ToolingLog({ + level: 'info', + writeTo: process.stdout, + }); + const es = new Cluster({ log }); + return { + es, + start: async () => { + await es.runServerless({ + basePath: ES_BASE_PATH_DIR, + teardown: true, + background: true, + clean: true, + kill: true, + waitForReady: true, + }); + return { + getClient: getServerlessESClient, + stop: async () => { + await es.stop(); + }, + }; + }, + }; +} + +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'], + }, + }, + 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, getServerlessDefault()), { + ...cliArgs, + serverless: true, + }); +} diff --git a/packages/core/test-helpers/core-test-helpers-kbn-server/src/index.ts b/packages/core/test-helpers/core-test-helpers-kbn-server/src/index.ts index 7a8e231066f8b..6fb64a34a0035 100644 --- a/packages/core/test-helpers/core-test-helpers-kbn-server/src/index.ts +++ b/packages/core/test-helpers/core-test-helpers-kbn-server/src/index.ts @@ -15,4 +15,12 @@ export { request, } from './create_root'; +export { createTestServerlessInstances } from './create_serverless_root'; + +export type { + TestServerlessUtils, + TestServerlessESUtils, + TestServerlessKibanaUtils, +} from './create_serverless_root'; + export type { HttpMethod, TestElasticsearchUtils, TestKibanaUtils, TestUtils } from './create_root'; diff --git a/packages/core/test-helpers/core-test-helpers-kbn-server/tsconfig.json b/packages/core/test-helpers/core-test-helpers-kbn-server/tsconfig.json index b5342c23fba2b..8afae2b7d74c3 100644 --- a/packages/core/test-helpers/core-test-helpers-kbn-server/tsconfig.json +++ b/packages/core/test-helpers/core-test-helpers-kbn-server/tsconfig.json @@ -18,6 +18,7 @@ "@kbn/core-root-server-internal", "@kbn/repo-info", "@kbn/repo-packages", + "@kbn/es", ], "exclude": [ "target/**/*", 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 7bdbdfd9e8ed7..75e23971bcbc7 100644 --- a/packages/deeplinks/search/constants.ts +++ b/packages/deeplinks/search/constants.ts @@ -7,4 +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 aa647955a5c17..420f308945ca3 100644 --- a/packages/deeplinks/search/deep_links.ts +++ b/packages/deeplinks/search/deep_links.ts @@ -6,9 +6,9 @@ * Side Public License, v 1. */ -import { SERVERLESS_ES_APP_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; +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/packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.test.ts b/packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.test.ts new file mode 100644 index 0000000000000..617d28b1acdcb --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/search/security/build_fields_request.test.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { 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 = buildAlertFieldsRequest(fields); + expect(fieldsRequest).toHaveLength(ALERT_EVENTS_FIELDS.length); + }); + + it('should not show ecs fields', () => { + const fields: string[] = []; + 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 = buildAlertFieldsRequest(fields, true); + expect(fieldsRequest).toEqual([{ field: 'showsup', include_unmapped: true }]); + }); + + it('should map provided fields with ecs fields', () => { + const fields = ['showsup']; + 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/packages/kbn-alerts-ui-shared/src/add_message_variables/index.test.tsx b/packages/kbn-alerts-ui-shared/src/add_message_variables/index.test.tsx new file mode 100644 index 0000000000000..80603d9eb8615 --- /dev/null +++ b/packages/kbn-alerts-ui-shared/src/add_message_variables/index.test.tsx @@ -0,0 +1,162 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 '.'; + +describe('AddMessageVariables', () => { + test('it renders variables and filter bar', async () => { + render( + + ); + + fireEvent.click(await screen.findByTestId('fooAddVariableButton')); + expect(screen.getByPlaceholderText('Filter options')).toBeInTheDocument(); + expect(screen.getByTestId('myVar-selectableOption')).toBeInTheDocument(); + expect(screen.getByTestId('myVar2-selectableOption')).toBeInTheDocument(); + }); + + test('it renders variables title and description', async () => { + render( + + ); + + fireEvent.click(await screen.findByTestId('fooAddVariableButton')); + expect(screen.getByText('myVar')).toBeInTheDocument(); + expect(screen.getByText('My variable description')).toBeInTheDocument(); + }); + + test('it renders tooltip when click on variable', async () => { + render( + + ); + + fireEvent.click(await screen.findByTestId('fooAddVariableButton')); + fireEvent.mouseOver(screen.getByText('My variable description')); + expect(await screen.findByTestId('myVar-tooltip')).toBeInTheDocument(); + }); + + test('onSelectEventHandler is called with proper action variable', async () => { + const onSelectEventHandler = jest.fn(); + render( + + ); + + fireEvent.click(await screen.findByTestId('fooAddVariableButton')); + fireEvent.click(screen.getByTestId('myVar2-selectableOption')); + + expect(onSelectEventHandler).toHaveBeenCalledTimes(1); + expect(onSelectEventHandler).toHaveBeenCalledWith({ + name: 'myVar2', + description: 'My variable 2 description', + useWithTripleBracesInTemplates: true, + }); + }); + + test('it renders deprecated variables as disabled', async () => { + render( + + ); + + fireEvent.click(await screen.findByTestId('fooAddVariableButton')); + fireEvent.click(screen.getByText('Show all')); + expect(screen.queryByTestId('myVar-selectableOption')).toBeInTheDocument(); + expect(screen.queryByTestId('deprecatedVar-selectableOption')).toBeInTheDocument(); + }); + + test(`it does't render when no variables exist`, async () => { + render( + + ); + + expect(screen.queryByTestId('fooAddVariableButton')).not.toBeInTheDocument(); + }); + + test('it renders button title when passed', async () => { + render( + + ); + + expect(await screen.findByText('Add variable')).toBeInTheDocument(); + }); +}); diff --git a/packages/kbn-alerts-ui-shared/src/add_message_variables/index.tsx b/packages/kbn-alerts-ui-shared/src/add_message_variables/index.tsx new file mode 100644 index 0000000000000..0aa9bae65c29e --- /dev/null +++ b/packages/kbn-alerts-ui-shared/src/add_message_variables/index.tsx @@ -0,0 +1,236 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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'; +import { + EuiPopover, + EuiButtonIcon, + EuiText, + EuiButtonEmpty, + EuiSelectable, + EuiSpacer, + EuiHighlight, + useEuiTheme, + EuiFlexGroup, + EuiFlexItem, + EuiPopoverFooter, + EuiToolTip, + EuiSelectableOption, +} from '@elastic/eui'; +import { ActionVariable } from '@kbn/alerting-plugin/common'; +import './add_message_variables.scss'; +import { TruncatedText } from './truncated_text'; +import * as i18n from './translations'; + +interface Props { + buttonTitle?: string; + messageVariables?: ActionVariable[]; + paramsProperty: string; + onSelectEventHandler: (variable: ActionVariable) => void; + showButtonTitle?: boolean; +} + +export const AddMessageVariables: React.FunctionComponent = ({ + buttonTitle, + messageVariables, + paramsProperty, + onSelectEventHandler, + showButtonTitle = false, +}) => { + const [isShowAllPressed, setIsShowAllPressed] = useState(false); + const [isVariablesPopoverOpen, setIsVariablesPopoverOpen] = useState(false); + + const { euiTheme } = useEuiTheme(); + + const messageVariablesObject: Record | undefined = useMemo( + () => + messageVariables?.reduce((acc, variable) => { + return { + ...acc, + [variable.name]: variable, + }; + }, {}), + [messageVariables] + ); + + const messageVariablesToShow = useMemo( + () => + isShowAllPressed + ? messageVariables + : messageVariables?.filter((variable) => !variable.deprecated), + [messageVariables, isShowAllPressed] + ); + + const optionsToShow = useMemo(() => { + return messageVariablesToShow?.map((variable) => ({ + label: variable.name, + ...(variable.deprecated ? { disabled: true } : {}), + data: { + description: variable.description, + }, + 'data-test-subj': `${variable.name}-selectableOption`, + })); + }, [messageVariablesToShow]); + + const addVariableButtonTitle = buttonTitle ? buttonTitle : i18n.ADD_VARIABLE_TITLE; + + const Button = useMemo( + () => + showButtonTitle ? ( + setIsVariablesPopoverOpen(true)} + aria-label={i18n.ADD_VARIABLE_POPOVER_BUTTON} + > + {addVariableButtonTitle} + + ) : ( + setIsVariablesPopoverOpen(true)} + iconType="indexOpen" + aria-label={i18n.ADD_VARIABLE_POPOVER_BUTTON} + /> + ), + [addVariableButtonTitle, paramsProperty, showButtonTitle] + ); + if ((messageVariables?.length ?? 0) === 0) { + return <>; + } + + const ToolTipContent = ({ description, label }: { description: string; label: string }) => { + return ( + <> + + {label} + + +
    + + {description} + + ); + }; + + const renderOption = ( + option: EuiSelectableOption<{ description?: string }>, + searchValue: string + ) => { + return ( + + + + {option.label} + + + {option.description && ( + <> + } + data-test-subj={`${option.label}-tooltip`} + > + + + + )} + + + ); + }; + + return ( + setIsVariablesPopoverOpen(false)} + panelPaddingSize="s" + anchorPosition="upRight" + panelStyle={{ minWidth: 350 }} + > + { + variables.map((variable) => { + if (variable.checked === 'on' && messageVariablesObject) { + onSelectEventHandler(messageVariablesObject[variable.label]); + } + }); + setIsVariablesPopoverOpen(false); + }} + singleSelection + searchProps={{ 'data-test-subj': 'messageVariablesSelectableSearch' }} + > + {(list, search) => ( + <> + {search} + + {list} + + + + + {isShowAllPressed + ? i18n.DEPRECATED_VARIABLES_ARE_SHOWN + : i18n.DEPRECATED_VARIABLES_ARE_HIDDEN} + + + + + isShowAllPressed ? setIsShowAllPressed(false) : setIsShowAllPressed(true) + } + > + {isShowAllPressed ? i18n.HIDE : i18n.SHOW_ALL} + + + + + + )} + + + ); +}; diff --git a/packages/kbn-alerts-ui-shared/src/add_message_variables/translations.ts b/packages/kbn-alerts-ui-shared/src/add_message_variables/translations.ts new file mode 100644 index 0000000000000..b19e9173797a9 --- /dev/null +++ b/packages/kbn-alerts-ui-shared/src/add_message_variables/translations.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; + +export const LOADING_VARIABLES = i18n.translate( + 'alertsUIShared.components.addMessageVariables.loadingMessage', + { + defaultMessage: 'Loading variables', + } +); + +export const NO_VARIABLES_FOUND = i18n.translate( + 'alertsUIShared.components.addMessageVariables.noVariablesFound', + { + defaultMessage: 'No variables found', + } +); + +export const NO_VARIABLES_AVAILABLE = i18n.translate( + 'alertsUIShared.components.addMessageVariables.noVariablesAvailable', + { + defaultMessage: 'No variables available', + } +); + +export const DEPRECATED_VARIABLES_ARE_SHOWN = i18n.translate( + 'alertsUIShared.components.addMessageVariables.deprecatedVariablesAreShown', + { + defaultMessage: 'Deprecated variables are shown', + } +); + +export const DEPRECATED_VARIABLES_ARE_HIDDEN = i18n.translate( + 'alertsUIShared.components.addMessageVariables.deprecatedVariablesAreHidden', + { + defaultMessage: 'Deprecated variables are hidden', + } +); + +export const HIDE = i18n.translate( + 'alertsUIShared.components.addMessageVariables.hideDeprecatedVariables', + { + defaultMessage: 'Hide', + } +); + +export const SHOW_ALL = i18n.translate( + 'alertsUIShared.components.addMessageVariables.showAllDeprecatedVariables', + { + defaultMessage: 'Show all', + } +); + +export const ADD_VARIABLE_POPOVER_BUTTON = i18n.translate( + 'alertsUIShared.components.addMessageVariables.addVariablePopoverButton', + { + defaultMessage: 'Add variable', + } +); + +export const ADD_VARIABLE_TITLE = i18n.translate( + '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-check-mappings-update-cli/current_mappings.json b/packages/kbn-check-mappings-update-cli/current_mappings.json index 3f70ed15952fb..c2e1b05850689 100644 --- a/packages/kbn-check-mappings-update-cli/current_mappings.json +++ b/packages/kbn-check-mappings-update-cli/current_mappings.json @@ -2956,8 +2956,34 @@ "risk-engine-configuration": { "dynamic": false, "properties": { + "dataViewId": { + "type": "keyword" + }, "enabled": { "type": "boolean" + }, + "filter": { + "dynamic": false, + "properties": {} + }, + "identifierType": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "pageSize": { + "type": "integer" + }, + "range": { + "properties": { + "start": { + "type": "keyword" + }, + "end": { + "type": "keyword" + } + } } } }, 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-discover-utils/src/utils/field_types.ts b/packages/kbn-discover-utils/src/utils/field_types.ts new file mode 100644 index 0000000000000..320f606dd0d8e --- /dev/null +++ b/packages/kbn-discover-utils/src/utils/field_types.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { 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 + * @public + */ +export enum KNOWN_FIELD_TYPES { + DOCUMENT = 'document', // "Records" on Lens page + BINARY = 'binary', + BOOLEAN = 'boolean', + CONFLICT = 'conflict', + COUNTER = 'counter', + DATE = 'date', + DATE_RANGE = 'date_range', + DENSE_VECTOR = 'dense_vector', + GAUGE = 'gauge', + GEO_POINT = 'geo_point', + GEO_SHAPE = 'geo_shape', + HISTOGRAM = 'histogram', + IP = 'ip', + IP_RANGE = 'ip_range', + FLATTENED = 'flattened', + KEYWORD = 'keyword', + MURMUR3 = 'murmur3', + NUMBER = 'number', + NESTED = 'nested', + RANK_FEATURE = 'rank_feature', + RANK_FEATURES = 'rank_features', + POINT = 'point', + SHAPE = 'shape', + STRING = 'string', + TEXT = 'text', + VERSION = 'version', +} + +export const KNOWN_FIELD_TYPE_LIST: string[] = Object.values(KNOWN_FIELD_TYPES); + +export const isKnownFieldType = (type?: string): type is FieldTypeKnown => { + return !!type && KNOWN_FIELD_TYPE_LIST.includes(type); +}; 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-discover-utils/src/utils/get_field_type_name.ts b/packages/kbn-discover-utils/src/utils/get_field_type_name.ts new file mode 100644 index 0000000000000..7e7bd102f3353 --- /dev/null +++ b/packages/kbn-discover-utils/src/utils/get_field_type_name.ts @@ -0,0 +1,151 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { KBN_FIELD_TYPES } from '@kbn/field-types'; +import { KNOWN_FIELD_TYPES } from './field_types'; + +/** + * A user-friendly name of an unknown field type + */ +export const UNKNOWN_FIELD_TYPE_MESSAGE = i18n.translate( + 'discover.fieldNameIcons.unknownFieldAriaLabel', + { + defaultMessage: 'Unknown field', + } +); + +/** + * Returns a user-friendly name of a field type + * @param type + * @public + */ +export function getFieldTypeName(type?: string) { + if (!type || type === KBN_FIELD_TYPES.UNKNOWN) { + return UNKNOWN_FIELD_TYPE_MESSAGE; + } + + if (type === 'source') { + // Note that this type is currently not provided, type for _source is undefined + return i18n.translate('discover.fieldNameIcons.sourceFieldAriaLabel', { + defaultMessage: 'Source field', + }); + } + + const knownType: KNOWN_FIELD_TYPES = type as KNOWN_FIELD_TYPES; + switch (knownType) { + case KNOWN_FIELD_TYPES.DOCUMENT: + return i18n.translate('discover.fieldNameIcons.recordAriaLabel', { + defaultMessage: 'Records', + }); + case KNOWN_FIELD_TYPES.BINARY: + return i18n.translate('discover.fieldNameIcons.binaryAriaLabel', { + defaultMessage: 'Binary', + }); + case KNOWN_FIELD_TYPES.BOOLEAN: + return i18n.translate('discover.fieldNameIcons.booleanAriaLabel', { + defaultMessage: 'Boolean', + }); + case KNOWN_FIELD_TYPES.CONFLICT: + return i18n.translate('discover.fieldNameIcons.conflictFieldAriaLabel', { + defaultMessage: 'Conflict', + }); + case KNOWN_FIELD_TYPES.COUNTER: + return i18n.translate('discover.fieldNameIcons.counterFieldAriaLabel', { + defaultMessage: 'Counter metric', + }); + case KNOWN_FIELD_TYPES.DATE: + return i18n.translate('discover.fieldNameIcons.dateFieldAriaLabel', { + defaultMessage: 'Date', + }); + case KNOWN_FIELD_TYPES.DATE_RANGE: + return i18n.translate('discover.fieldNameIcons.dateRangeFieldAriaLabel', { + defaultMessage: 'Date range', + }); + case KNOWN_FIELD_TYPES.DENSE_VECTOR: + return i18n.translate('discover.fieldNameIcons.denseVectorFieldAriaLabel', { + defaultMessage: 'Dense vector', + }); + case KNOWN_FIELD_TYPES.GAUGE: + return i18n.translate('discover.fieldNameIcons.gaugeFieldAriaLabel', { + defaultMessage: 'Gauge metric', + }); + case KNOWN_FIELD_TYPES.GEO_POINT: + return i18n.translate('discover.fieldNameIcons.geoPointFieldAriaLabel', { + defaultMessage: 'Geo point', + }); + case KNOWN_FIELD_TYPES.GEO_SHAPE: + return i18n.translate('discover.fieldNameIcons.geoShapeFieldAriaLabel', { + defaultMessage: 'Geo shape', + }); + case KNOWN_FIELD_TYPES.HISTOGRAM: + return i18n.translate('discover.fieldNameIcons.histogramFieldAriaLabel', { + defaultMessage: 'Histogram', + }); + case KNOWN_FIELD_TYPES.IP: + return i18n.translate('discover.fieldNameIcons.ipAddressFieldAriaLabel', { + defaultMessage: 'IP address', + }); + case KNOWN_FIELD_TYPES.IP_RANGE: + return i18n.translate('discover.fieldNameIcons.ipRangeFieldAriaLabel', { + defaultMessage: 'IP range', + }); + case KNOWN_FIELD_TYPES.FLATTENED: + return i18n.translate('discover.fieldNameIcons.flattenedFieldAriaLabel', { + defaultMessage: 'Flattened', + }); + case KNOWN_FIELD_TYPES.MURMUR3: + return i18n.translate('discover.fieldNameIcons.murmur3FieldAriaLabel', { + defaultMessage: 'Murmur3', + }); + case KNOWN_FIELD_TYPES.NUMBER: + return i18n.translate('discover.fieldNameIcons.numberFieldAriaLabel', { + defaultMessage: 'Number', + }); + case KNOWN_FIELD_TYPES.RANK_FEATURE: + return i18n.translate('discover.fieldNameIcons.rankFeatureFieldAriaLabel', { + defaultMessage: 'Rank feature', + }); + case KNOWN_FIELD_TYPES.RANK_FEATURES: + return i18n.translate('discover.fieldNameIcons.rankFeaturesFieldAriaLabel', { + defaultMessage: 'Rank features', + }); + case KNOWN_FIELD_TYPES.POINT: + return i18n.translate('discover.fieldNameIcons.pointFieldAriaLabel', { + defaultMessage: 'Point', + }); + case KNOWN_FIELD_TYPES.SHAPE: + return i18n.translate('discover.fieldNameIcons.shapeFieldAriaLabel', { + defaultMessage: 'Shape', + }); + case KNOWN_FIELD_TYPES.STRING: + return i18n.translate('discover.fieldNameIcons.stringFieldAriaLabel', { + defaultMessage: 'String', + }); + case KNOWN_FIELD_TYPES.TEXT: + return i18n.translate('discover.fieldNameIcons.textFieldAriaLabel', { + defaultMessage: 'Text', + }); + case KNOWN_FIELD_TYPES.KEYWORD: + return i18n.translate('discover.fieldNameIcons.keywordFieldAriaLabel', { + defaultMessage: 'Keyword', + }); + case KNOWN_FIELD_TYPES.NESTED: + return i18n.translate('discover.fieldNameIcons.nestedFieldAriaLabel', { + defaultMessage: 'Nested', + }); + case KNOWN_FIELD_TYPES.VERSION: + return i18n.translate('discover.fieldNameIcons.versionFieldAriaLabel', { + defaultMessage: 'Version', + }); + default: + // If you see a typescript error here, that's a sign that there are missing switch cases ^^ + const _exhaustiveCheck: never = knownType; + return knownType || _exhaustiveCheck; + } +} 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 a3aebffc12b55..a8d63137fa0a9 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -34,6 +34,8 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { const WORKPLACE_SEARCH_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/workplace-search/${DOC_LINK_VERSION}/`; const SEARCH_UI_DOCS = `${DOCS_WEBSITE_URL}search-ui/`; const MACHINE_LEARNING_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/`; + const SERVERLESS_DOCS = `${DOCS_WEBSITE_URL}serverless/`; + const SERVERLESS_ELASTICSEARCH_DOCS = `${SERVERLESS_DOCS}elasticsearch/`; return deepFreeze({ settings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/settings.html`, @@ -65,6 +67,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { }, console: { guide: `${KIBANA_DOCS}console-kibana.html`, + serverlessGuide: `${SERVERLESS_ELASTICSEARCH_DOCS}dev-tools-console`, }, dashboard: { guide: `${KIBANA_DOCS}dashboard.html`, @@ -619,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`, @@ -805,8 +809,29 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { appSearch: `${SEARCH_UI_DOCS}tutorials/app-search`, elasticsearch: `${SEARCH_UI_DOCS}tutorials/elasticsearch`, }, + serverlessClients: { + goApiReference: `${SERVERLESS_ELASTICSEARCH_DOCS}go-apis-references`, + goGettingStarted: `${SERVERLESS_ELASTICSEARCH_DOCS}go-apis`, + httpApis: `${SERVERLESS_ELASTICSEARCH_DOCS}http-apis`, + httpApiReferences: `${SERVERLESS_ELASTICSEARCH_DOCS}http-apis-references`, + jsApiReference: `${SERVERLESS_ELASTICSEARCH_DOCS}nodejs-apis-references`, + jsGettingStarted: `${SERVERLESS_ELASTICSEARCH_DOCS}nodejs-apis-getting-started`, + phpApiReference: `${SERVERLESS_ELASTICSEARCH_DOCS}php-apis-references`, + phpGettingStarted: `${SERVERLESS_ELASTICSEARCH_DOCS}php-apis-getting-started`, + pythonApiReference: `${SERVERLESS_ELASTICSEARCH_DOCS}python-apis-references`, + pythonGettingStarted: `${SERVERLESS_ELASTICSEARCH_DOCS}python-apis-getting-started`, + pythonReferences: `${SERVERLESS_ELASTICSEARCH_DOCS}python-apis-references`, + rubyApiReference: `${SERVERLESS_ELASTICSEARCH_DOCS}ruby-apis-references`, + rubyGettingStarted: `${SERVERLESS_ELASTICSEARCH_DOCS}ruby-apis-getting-started`, + }, serverlessSearch: { - integrations: `${ELASTIC_WEBSITE_URL}/integrations`, + integrations: `${SERVERLESS_ELASTICSEARCH_DOCS}ingest-data-through-integrations`, + integrationsLogstash: `${SERVERLESS_ELASTICSEARCH_DOCS}ingest-data-through-integrations-logstash`, + integrationsBeats: `${SERVERLESS_ELASTICSEARCH_DOCS}ingest-data-through-integrations-beats`, + integrationsConnectorClient: `${SERVERLESS_ELASTICSEARCH_DOCS}ingest-data-through-integrations-connector-client`, + gettingStartedExplore: `${SERVERLESS_ELASTICSEARCH_DOCS}get-started-explore`, + gettingStartedIngest: `${SERVERLESS_ELASTICSEARCH_DOCS}get-started-ingest`, + gettingStartedSearch: `${SERVERLESS_ELASTICSEARCH_DOCS}get-started-search`, }, synthetics: { featureRoles: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/synthetics-feature-roles.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 1a6726b743949..428ef86267dd1 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -49,6 +49,7 @@ export interface DocLinks { }; readonly console: { readonly guide: string; + readonly serverlessGuide: string; }; readonly dashboard: { readonly guide: string; @@ -360,6 +361,7 @@ export interface DocLinks { readonly visualize: Record; readonly apis: Readonly<{ bulkIndexAlias: string; + indexStats: string; byteSizeUnits: string; createAutoFollowPattern: string; createFollower: string; @@ -569,8 +571,29 @@ export interface DocLinks { readonly appSearch: string; readonly elasticsearch: string; }; + readonly serverlessClients: { + readonly goApiReference: string; + readonly goGettingStarted: string; + readonly httpApis: string; + readonly httpApiReferences: string; + readonly jsApiReference: string; + readonly jsGettingStarted: string; + readonly phpApiReference: string; + readonly phpGettingStarted: string; + readonly pythonApiReference: string; + readonly pythonGettingStarted: string; + readonly pythonReferences: string; + readonly rubyApiReference: string; + readonly rubyGettingStarted: string; + }; readonly serverlessSearch: { + readonly gettingStartedExplore: string; + readonly gettingStartedIngest: string; + readonly gettingStartedSearch: string; readonly integrations: string; + readonly integrationsBeats: string; + readonly integrationsConnectorClient: string; + readonly integrationsLogstash: string; }; readonly synthetics: { readonly featureRoles: 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_aggregate_query.test.ts b/packages/kbn-es-query/src/es_query/es_aggregate_query.test.ts new file mode 100644 index 0000000000000..2ab161e0f7517 --- /dev/null +++ b/packages/kbn-es-query/src/es_query/es_aggregate_query.test.ts @@ -0,0 +1,101 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + isOfQueryType, + isOfAggregateQueryType, + getAggregateQueryMode, + getIndexPatternFromSQLQuery, + getIndexPatternFromESQLQuery, +} from './es_aggregate_query'; + +describe('sql query helpers', () => { + describe('isOfQueryType', () => { + it('should return true for a Query type query', () => { + const flag = isOfQueryType({ query: 'foo', language: 'test' }); + expect(flag).toBe(true); + }); + + it('should return false for an Aggregate type query', () => { + const flag = isOfQueryType({ sql: 'SELECT * FROM foo' }); + expect(flag).toBe(false); + }); + }); + + describe('isOfAggregateQueryType', () => { + it('should return false for a Query type query', () => { + const flag = isOfAggregateQueryType({ query: 'foo', language: 'test' }); + expect(flag).toBe(false); + }); + + it('should return true for an Aggregate type query', () => { + const flag = isOfAggregateQueryType({ sql: 'SELECT * FROM foo' }); + expect(flag).toBe(true); + }); + }); + + describe('getAggregateQueryMode', () => { + it('should return sql for an SQL AggregateQuery type', () => { + const mode = getAggregateQueryMode({ sql: 'SELECT * FROM foo' }); + expect(mode).toBe('sql'); + }); + + it('should return esql for an ESQL AggregateQuery type', () => { + const mode = getAggregateQueryMode({ esql: 'foo | where field > 100' }); + expect(mode).toBe('esql'); + }); + }); + + describe('getIndexPatternFromSQLQuery', () => { + it('should return the index pattern string from sql queries', () => { + const idxPattern1 = getIndexPatternFromSQLQuery('SELECT * FROM foo'); + expect(idxPattern1).toBe('foo'); + + const idxPattern2 = getIndexPatternFromSQLQuery('SELECT woof, meow FROM "foo"'); + expect(idxPattern2).toBe('foo'); + + const idxPattern3 = getIndexPatternFromSQLQuery('SELECT woof, meow FROM "the_index_pattern"'); + expect(idxPattern3).toBe('the_index_pattern'); + + const idxPattern4 = getIndexPatternFromSQLQuery('SELECT woof, meow FROM "the-index-pattern"'); + expect(idxPattern4).toBe('the-index-pattern'); + + const idxPattern5 = getIndexPatternFromSQLQuery('SELECT woof, meow from "the-index-pattern"'); + expect(idxPattern5).toBe('the-index-pattern'); + + const idxPattern6 = getIndexPatternFromSQLQuery('SELECT woof, meow from "logstash-*"'); + expect(idxPattern6).toBe('logstash-*'); + + const idxPattern7 = getIndexPatternFromSQLQuery( + 'SELECT woof, meow from logstash-1234! WHERE field > 100' + ); + expect(idxPattern7).toBe('logstash-1234!'); + + const idxPattern8 = getIndexPatternFromSQLQuery( + 'SELECT * FROM (SELECT woof, miaou FROM "logstash-1234!" GROUP BY woof)' + ); + 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_aggregate_query.ts b/packages/kbn-es-query/src/es_query/es_aggregate_query.ts new file mode 100644 index 0000000000000..1e87552e98b83 --- /dev/null +++ b/packages/kbn-es-query/src/es_query/es_aggregate_query.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import type { Query, AggregateQuery } from '../filters'; + +type Language = keyof AggregateQuery; + +// Checks if the query is of type Query +export function isOfQueryType(arg?: Query | AggregateQuery): arg is Query { + return Boolean(arg && 'query' in arg); +} + +// Checks if the query is of type AggregateQuery +// currently only supports the sql query type +// should be enhanced to support other query types +export function isOfAggregateQueryType( + query: AggregateQuery | Query | { [key: string]: any } +): query is AggregateQuery { + return Boolean(query && ('sql' in query || 'esql' in query)); +} + +// returns the language of the aggregate Query, sql, esql etc +export function getAggregateQueryMode(query: AggregateQuery): Language { + return Object.keys(query)[0] as Language; +} + +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')); + const fromsLength = splitFroms?.length ?? 0; + if (splitFroms && splitFroms?.length > 2) { + sql = `${splitFroms[fromsLength - 2]} FROM ${splitFroms[fromsLength - 1]}`; + } + // case insensitive match for the index pattern + const regex = new RegExp(/FROM\s+([\w*-.!@$^()~;]+)/, 'i'); + const matches = sql?.match(regex); + if (matches) { + return matches[1]; + } + 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/es_query_sql.test.ts b/packages/kbn-es-query/src/es_query/es_query_sql.test.ts deleted file mode 100644 index da909c6e5f9b4..0000000000000 --- a/packages/kbn-es-query/src/es_query/es_query_sql.test.ts +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { - isOfQueryType, - isOfAggregateQueryType, - getAggregateQueryMode, - getIndexPatternFromSQLQuery, -} from './es_query_sql'; - -describe('sql query helpers', () => { - describe('isOfQueryType', () => { - it('should return true for a Query type query', () => { - const flag = isOfQueryType({ query: 'foo', language: 'test' }); - expect(flag).toBe(true); - }); - - it('should return false for an Aggregate type query', () => { - const flag = isOfQueryType({ sql: 'SELECT * FROM foo' }); - expect(flag).toBe(false); - }); - }); - - describe('isOfAggregateQueryType', () => { - it('should return false for a Query type query', () => { - const flag = isOfAggregateQueryType({ query: 'foo', language: 'test' }); - expect(flag).toBe(false); - }); - - it('should return true for an Aggregate type query', () => { - const flag = isOfAggregateQueryType({ sql: 'SELECT * FROM foo' }); - expect(flag).toBe(true); - }); - }); - - describe('getAggregateQueryMode', () => { - it('should return sql for an SQL AggregateQuery type', () => { - const mode = getAggregateQueryMode({ sql: 'SELECT * FROM foo' }); - expect(mode).toBe('sql'); - }); - - it('should return esql for an ESQL AggregateQuery type', () => { - const mode = getAggregateQueryMode({ esql: 'foo | where field > 100' }); - expect(mode).toBe('esql'); - }); - }); - - describe('getIndexPatternFromSQLQuery', () => { - it('should return the index pattern string from sql queries', () => { - const idxPattern1 = getIndexPatternFromSQLQuery('SELECT * FROM foo'); - expect(idxPattern1).toBe('foo'); - - const idxPattern2 = getIndexPatternFromSQLQuery('SELECT woof, meow FROM "foo"'); - expect(idxPattern2).toBe('foo'); - - const idxPattern3 = getIndexPatternFromSQLQuery('SELECT woof, meow FROM "the_index_pattern"'); - expect(idxPattern3).toBe('the_index_pattern'); - - const idxPattern4 = getIndexPatternFromSQLQuery('SELECT woof, meow FROM "the-index-pattern"'); - expect(idxPattern4).toBe('the-index-pattern'); - - const idxPattern5 = getIndexPatternFromSQLQuery('SELECT woof, meow from "the-index-pattern"'); - expect(idxPattern5).toBe('the-index-pattern'); - - const idxPattern6 = getIndexPatternFromSQLQuery('SELECT woof, meow from "logstash-*"'); - expect(idxPattern6).toBe('logstash-*'); - - const idxPattern7 = getIndexPatternFromSQLQuery( - 'SELECT woof, meow from logstash-1234! WHERE field > 100' - ); - expect(idxPattern7).toBe('logstash-1234!'); - - const idxPattern8 = getIndexPatternFromSQLQuery( - 'SELECT * FROM (SELECT woof, miaou FROM "logstash-1234!" GROUP BY woof)' - ); - expect(idxPattern8).toBe('logstash-1234!'); - }); - }); -}); diff --git a/packages/kbn-es-query/src/es_query/es_query_sql.ts b/packages/kbn-es-query/src/es_query/es_query_sql.ts deleted file mode 100644 index 46de33dc04e86..0000000000000 --- a/packages/kbn-es-query/src/es_query/es_query_sql.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { Query, AggregateQuery } from '../filters'; - -type Language = keyof AggregateQuery; - -// Checks if the query is of type Query -export function isOfQueryType(arg?: Query | AggregateQuery): arg is Query { - return Boolean(arg && 'query' in arg); -} - -// Checks if the query is of type AggregateQuery -// currently only supports the sql query type -// should be enhanced to support other query types -export function isOfAggregateQueryType( - query: AggregateQuery | Query | { [key: string]: any } -): query is AggregateQuery { - return Boolean(query && ('sql' in query || 'esql' in query)); -} - -// returns the language of the aggregate Query, sql, esql etc -export function getAggregateQueryMode(query: AggregateQuery): Language { - return Object.keys(query)[0] as Language; -} - -// retrieves the index pattern from the aggregate query -export function getIndexPatternFromSQLQuery(sqlQuery?: string): string { - let sql = sqlQuery?.replaceAll('"', '').replaceAll("'", ''); - const splitFroms = sql?.split(new RegExp(/FROM\s/, 'ig')); - const fromsLength = splitFroms?.length ?? 0; - if (splitFroms && splitFroms?.length > 2) { - sql = `${splitFroms[fromsLength - 2]} FROM ${splitFroms[fromsLength - 1]}`; - } - // case insensitive match for the index pattern - const regex = new RegExp(/FROM\s+([\w*-.!@$^()~;]+)/, 'i'); - const matches = sql?.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-repo-packages/modern/plugins.js b/packages/kbn-repo-packages/modern/plugins.js index a197c6a679771..31dd08bf1f5ba 100644 --- a/packages/kbn-repo-packages/modern/plugins.js +++ b/packages/kbn-repo-packages/modern/plugins.js @@ -107,11 +107,7 @@ function getPluginPackagesFilter(selector = {}) { */ function getDistributablePacakgesFilter() { return (pkg) => { - if ( - pkg.isDevOnly || - pkg.manifest.type === 'functional-tests' || - pkg.manifest.type === 'test-helper' - ) { + if (pkg.isDevOnly()) { return false; } 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 9083cf902f885..6d56f69e09530 100644 --- a/packages/kbn-search-api-panels/components/install_client.tsx +++ b/packages/kbn-search-api-panels/components/install_client.tsx @@ -10,21 +10,19 @@ 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'; import { OverviewPanel } from './overview_panel'; -import { LanguageDefinition, Languages } from '../types'; +import { LanguageDefinition } from '../types'; 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,57 +30,29 @@ interface InstallClientProps { overviewPanelProps?: Partial; } -const Link: React.FC<{ language: Languages; http: HttpStart; pluginId: string }> = ({ +const Link: React.FC<{ language: LanguageDefinition; assetBasePath: string }> = ({ language, - http, - pluginId, + assetBasePath, }) => { - switch (language) { - case Languages.CURL: - return ( - - ); - case Languages.JAVASCRIPT: - return ( - - ); - case Languages.RUBY: - return ( - - ); + if (language.github) { + return ( + + ); } return null; }; export const InstallClientPanel: React.FC = ({ codeSnippet, - showTryInConsole, + consoleRequest, language, languages, setSelectedLanguage, - http, - pluginId, + assetBasePath, application, sharePlugin, isPanelLeft = true, @@ -91,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/packages/kbn-search-api-panels/index.tsx b/packages/kbn-search-api-panels/index.tsx index d3781084eacae..feb26ae501de7 100644 --- a/packages/kbn-search-api-panels/index.tsx +++ b/packages/kbn-search-api-panels/index.tsx @@ -21,6 +21,7 @@ export * from './components/try_in_console_button'; export * from './components/install_client'; export * from './types'; +export * from './utils'; export interface WelcomeBannerProps { userProfile: { diff --git a/packages/kbn-search-api-panels/languages/console.ts b/packages/kbn-search-api-panels/languages/console.ts new file mode 100644 index 0000000000000..be924d5fa3cbf --- /dev/null +++ b/packages/kbn-search-api-panels/languages/console.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 { LanguageDefinition } from '../types'; + +export const consoleDefinition: Partial = { + buildSearchQuery: `POST /books/_search?pretty +{ + "query": { + "query_string": { + "query": "snow" + } + } +}`, + ingestData: `POST _bulk?pretty +{ "index" : { "_index" : "books" } } +{"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} +{ "index" : { "_index" : "books" } } +{"name": "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585} +{ "index" : { "_index" : "books" } } +{"name": "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328} +{ "index" : { "_index" : "books" } } +{"name": "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227} +{ "index" : { "_index" : "books" } } +{"name": "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} +{ "index" : { "_index" : "books" } } +{"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311}`, +}; diff --git a/packages/kbn-search-api-panels/types.ts b/packages/kbn-search-api-panels/types.ts index 1d35f440673de..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); @@ -32,6 +33,10 @@ export interface LanguageDefinition { basicConfig?: string; configureClient: CodeSnippet; docLink: string; + github?: { + link: string; + label: string; + }; iconType: string; id: Languages; ingestData: CodeSnippet; diff --git a/packages/kbn-search-api-panels/utils.ts b/packages/kbn-search-api-panels/utils.ts new file mode 100644 index 0000000000000..ffd81257c5a30 --- /dev/null +++ b/packages/kbn-search-api-panels/utils.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { LanguageDefinition, LanguageDefinitionSnippetArguments } from './types'; +import { consoleDefinition } from './languages/console'; + +export const getLanguageDefinitionCodeSnippet = ( + language: Partial, + key: keyof LanguageDefinition, + args: LanguageDefinitionSnippetArguments +): string => { + const snippetVal = language[key]; + if (snippetVal === undefined) return ''; + switch (typeof snippetVal) { + case 'string': + return snippetVal; + case 'function': + return snippetVal(args); + default: + 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-autocomplete/src/field_value_lists/index.test.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.test.tsx index 6cd92fe1a1b35..acd1a315d2c48 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.test.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.test.tsx @@ -211,6 +211,7 @@ describe('AutocompleteFieldListsComponent', () => { await waitFor(() => { expect(mockOnChange).toHaveBeenCalledWith({ + '@timestamp': DATE_NOW, _version: undefined, created_at: DATE_NOW, created_by: 'some user', diff --git a/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts b/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts index 9dca48e2d8b38..9875db2fab1f1 100644 --- a/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts +++ b/packages/kbn-securitysolution-autocomplete/src/list_schema/index.mock.ts @@ -42,6 +42,7 @@ export const NAME = 'some name'; // TODO: Once this mock is available within packages, use it instead, https://github.com/elastic/kibana/issues/100715 // import { getListResponseMock } from '../../../../../lists/common/schemas/response/list_schema.mock'; export const getListResponseMock = (): ListSchema => ({ + '@timestamp': DATE_NOW, _version: undefined, created_at: DATE_NOW, created_by: USER, diff --git a/packages/kbn-securitysolution-es-utils/index.ts b/packages/kbn-securitysolution-es-utils/index.ts index 94aed92969627..049d5a7de492c 100644 --- a/packages/kbn-securitysolution-es-utils/index.ts +++ b/packages/kbn-securitysolution-es-utils/index.ts @@ -8,8 +8,10 @@ export * from './src/bad_request_error'; export * from './src/create_boostrap_index'; +export * from './src/create_data_stream'; export * from './src/decode_version'; export * from './src/delete_all_index'; +export * from './src/delete_data_stream'; export * from './src/delete_index_template'; export * from './src/delete_policy'; export * from './src/delete_template'; @@ -18,11 +20,15 @@ export * from './src/get_bootstrap_index_exists'; export * from './src/get_index_aliases'; export * from './src/get_index_count'; export * from './src/get_index_exists'; +export * from './src/get_data_stream_exists'; export * from './src/get_index_template_exists'; export * from './src/get_policy_exists'; export * from './src/get_template_exists'; +export * from './src/migrate_to_data_stream'; export * from './src/read_index'; export * from './src/read_privileges'; +export * from './src/put_mappings'; +export * from './src/remove_policy_from_index'; export * from './src/set_index_template'; export * from './src/set_policy'; export * from './src/set_template'; diff --git a/packages/kbn-securitysolution-es-utils/src/create_data_stream/index.ts b/packages/kbn-securitysolution-es-utils/src/create_data_stream/index.ts new file mode 100644 index 0000000000000..95427cc7aec56 --- /dev/null +++ b/packages/kbn-securitysolution-es-utils/src/create_data_stream/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 type { ElasticsearchClient } from '../elasticsearch_client'; + +/** + * creates data stream + * @param esClient + * @param name + */ +export const createDataStream = async ( + esClient: ElasticsearchClient, + name: string +): Promise => { + return esClient.indices.createDataStream({ + name, + }); +}; diff --git a/packages/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts b/packages/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts new file mode 100644 index 0000000000000..23009be11165e --- /dev/null +++ b/packages/kbn-securitysolution-es-utils/src/delete_data_stream/index.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ElasticsearchClient } from '../elasticsearch_client'; + +/** + * deletes data stream + * @param esClient + * @param name + */ +export const deleteDataStream = async ( + esClient: ElasticsearchClient, + name: string +): Promise => { + return ( + await esClient.indices.deleteDataStream( + { + name, + }, + { meta: true } + ) + ).body.acknowledged; +}; diff --git a/packages/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts b/packages/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts new file mode 100644 index 0000000000000..8d5419405147a --- /dev/null +++ b/packages/kbn-securitysolution-es-utils/src/get_data_stream_exists/index.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ElasticsearchClient } from '../elasticsearch_client'; + +/** + * checks if data stream exists + * @param esClient + * @param name + */ +export const getDataStreamExists = async ( + esClient: ElasticsearchClient, + name: string +): Promise => { + try { + const body = await esClient.indices.getDataStream({ name, expand_wildcards: 'all' }); + return body.data_streams.length > 0; + } catch (err) { + if (err.body != null && err.body.status === 404) { + return false; + } else if ( + // if index already created, _data_stream/${name} request will produce the following error + // data stream does not exist at this point, so we can return false + err?.body?.error?.reason?.includes( + `The provided expression [${name}] matches an alias, specify the corresponding concrete indices instead.` + ) + ) { + return false; + } else { + throw err.body ? err.body : err; + } + } +}; diff --git a/packages/kbn-securitysolution-es-utils/src/migrate_to_data_stream/index.ts b/packages/kbn-securitysolution-es-utils/src/migrate_to_data_stream/index.ts new file mode 100644 index 0000000000000..1ec831846e38f --- /dev/null +++ b/packages/kbn-securitysolution-es-utils/src/migrate_to_data_stream/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 type { ElasticsearchClient } from '../elasticsearch_client'; + +/** + * migrate to data stream + * @param esClient + * @param name + */ +export const migrateToDataStream = async ( + esClient: ElasticsearchClient, + name: string +): Promise => { + return esClient.indices.migrateToDataStream({ + name, + }); +}; diff --git a/packages/kbn-securitysolution-es-utils/src/put_mappings/index.ts b/packages/kbn-securitysolution-es-utils/src/put_mappings/index.ts new file mode 100644 index 0000000000000..8a7c6c2b51a90 --- /dev/null +++ b/packages/kbn-securitysolution-es-utils/src/put_mappings/index.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { MappingProperty } from '@elastic/elasticsearch/lib/api/types'; +import type { ElasticsearchClient } from '../elasticsearch_client'; + +/** + * update mappings of index + * @param esClient + * @param index + * @param mappings + */ +export const putMappings = async ( + esClient: ElasticsearchClient, + index: string, + mappings: Record +): Promise => { + return await esClient.indices.putMapping({ + index, + properties: mappings, + }); +}; diff --git a/packages/kbn-securitysolution-es-utils/src/remove_policy_from_index/index.ts b/packages/kbn-securitysolution-es-utils/src/remove_policy_from_index/index.ts new file mode 100644 index 0000000000000..0b77c112a833f --- /dev/null +++ b/packages/kbn-securitysolution-es-utils/src/remove_policy_from_index/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 type { ElasticsearchClient } from '../elasticsearch_client'; + +export const removePolicyFromIndex = async ( + esClient: ElasticsearchClient, + index: string +): Promise => { + return (await esClient.ilm.removePolicy({ index }, { meta: true })).body; +}; 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-io-ts-list-types/src/common/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts index e50500f87f61a..9c7e1a4ad31b5 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts @@ -56,6 +56,7 @@ export * from './sort_field'; export * from './sort_order'; export * from './tags'; export * from './tie_breaker_id'; +export * from './timestamp'; export * from './total'; export * from './type'; export * from './underscore_version'; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts index 93c38facd8f4e..93376f3112530 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/meta/index.ts @@ -12,3 +12,6 @@ export const meta = t.object; export type Meta = t.TypeOf; export const metaOrUndefined = t.union([meta, t.undefined]); export type MetaOrUndefined = t.TypeOf; + +export const nullableMetaOrUndefined = t.union([metaOrUndefined, t.null]); +export type NullableMetaOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/index.ts new file mode 100644 index 0000000000000..e4b89c7590530 --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/timestamp/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 * as t from 'io-ts'; +import { IsoDateString } from '@kbn/securitysolution-io-ts-types'; + +export const timestamp = IsoDateString; +export const timestampOrUndefined = t.union([IsoDateString, t.undefined]); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts index 33d3b49cf5492..3b85f03e2facb 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.mock.ts @@ -21,6 +21,7 @@ import { export const getListItemResponseMock = (): ListItemSchema => ({ _version: undefined, + '@timestamp': DATE_NOW, created_at: DATE_NOW, created_by: USER, deserializer: undefined, diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts index ae75f3a7741bc..4a45903c82d98 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_item_schema/index.ts @@ -11,6 +11,7 @@ import * as t from 'io-ts'; import { _versionOrUndefined } from '../../common/underscore_version'; import { deserializerOrUndefined } from '../../common/deserializer'; import { metaOrUndefined } from '../../common/meta'; +import { timestampOrUndefined } from '../../common/timestamp'; import { serializerOrUndefined } from '../../common/serializer'; import { created_at } from '../../common/created_at'; import { created_by } from '../../common/created_by'; @@ -25,6 +26,7 @@ import { value } from '../../common/value'; export const listItemSchema = t.exact( t.type({ _version: _versionOrUndefined, + '@timestamp': timestampOrUndefined, created_at, created_by, deserializer: deserializerOrUndefined, diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts index 3c78c0cdbc976..6ca277659c078 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.mock.ts @@ -23,6 +23,7 @@ import { export const getListResponseMock = (): ListSchema => ({ _version: undefined, + '@timestamp': DATE_NOW, created_at: DATE_NOW, created_by: USER, description: DESCRIPTION, diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts index 9db686e6de255..a9f076384fdf8 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/response/list_schema/index.ts @@ -13,6 +13,7 @@ import { deserializerOrUndefined } from '../../common/deserializer'; import { metaOrUndefined } from '../../common/meta'; import { serializerOrUndefined } from '../../common/serializer'; import { created_at } from '../../common/created_at'; +import { timestampOrUndefined } from '../../common/timestamp'; import { created_by } from '../../common/created_by'; import { description } from '../../common/description'; import { id } from '../../common/id'; @@ -26,6 +27,7 @@ import { updated_by } from '../../common/updated_by'; export const listSchema = t.exact( t.type({ _version: _versionOrUndefined, + '@timestamp': timestampOrUndefined, created_at, created_by, description, diff --git a/packages/kbn-securitysolution-list-api/src/api/index.ts b/packages/kbn-securitysolution-list-api/src/api/index.ts index 07d1b677a76bf..98b83b6279953 100644 --- a/packages/kbn-securitysolution-list-api/src/api/index.ts +++ b/packages/kbn-securitysolution-list-api/src/api/index.ts @@ -37,7 +37,7 @@ import { import { ENDPOINT_LIST_URL, - EXCEPTION_FILTER, + INTERNAL_EXCEPTION_FILTER, EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL, } from '@kbn/securitysolution-list-constants'; @@ -579,8 +579,9 @@ export const getExceptionFilterFromExceptionListIds = async ({ http, signal, }: GetExceptionFilterFromExceptionListIdsProps): Promise => - http.fetch(EXCEPTION_FILTER, { + http.fetch(INTERNAL_EXCEPTION_FILTER, { method: 'POST', + version: '1', body: JSON.stringify({ exception_list_ids: exceptionListIds, type: 'exception_list_ids', @@ -607,8 +608,9 @@ export const getExceptionFilterFromExceptions = async ({ chunkSize, signal, }: GetExceptionFilterFromExceptionsProps): Promise => - http.fetch(EXCEPTION_FILTER, { + 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 a7ca546ea2eef..5c280c7959763 100644 --- a/packages/kbn-securitysolution-list-api/src/list_api/index.ts +++ b/packages/kbn-securitysolution-list-api/src/list_api/index.ts @@ -37,7 +37,7 @@ import { LIST_ITEM_URL, LIST_PRIVILEGES_URL, LIST_URL, - FIND_LISTS_BY_SIZE, + INTERNAL_FIND_LISTS_BY_SIZE, } from '@kbn/securitysolution-list-constants'; import { toError, toPromise } from '../fp_utils'; @@ -115,8 +115,9 @@ const findListsBySize = async ({ per_page, signal, }: ApiParams & FindListSchemaEncoded): Promise => { - return http.fetch(`${FIND_LISTS_BY_SIZE}`, { + 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-list-api/src/list_api/mocks/response/list_schema.mock.ts b/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_schema.mock.ts index 5421b4557c617..348c0506c9b26 100644 --- a/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_schema.mock.ts +++ b/packages/kbn-securitysolution-list-api/src/list_api/mocks/response/list_schema.mock.ts @@ -23,6 +23,7 @@ import { } from '../constants.mock'; export const getListResponseMock = (): ListSchema => ({ + '@timestamp': DATE_NOW, _version: undefined, created_at: DATE_NOW, created_by: USER, diff --git a/packages/kbn-securitysolution-list-constants/index.ts b/packages/kbn-securitysolution-list-constants/index.ts index 7bc44b534caf2..42249d5f305e9 100644 --- a/packages/kbn-securitysolution-list-constants/index.ts +++ b/packages/kbn-securitysolution-list-constants/index.ts @@ -20,8 +20,8 @@ export const LIST_PRIVILEGES_URL = `${LIST_URL}/privileges`; * Internal value list routes */ export const INTERNAL_LIST_URL = '/internal/lists'; -export const FIND_LISTS_BY_SIZE = `${INTERNAL_LIST_URL}/_find_lists_by_size` as const; -export const EXCEPTION_FILTER = `${INTERNAL_LIST_URL}/_create_filter` as const; +export const INTERNAL_FIND_LISTS_BY_SIZE = `${INTERNAL_LIST_URL}/_find_lists_by_size` as const; +export const INTERNAL_EXCEPTION_FILTER = `${INTERNAL_LIST_URL}/_create_filter` as const; /** * Exception list routes diff --git a/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts b/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts index 5421b4557c617..348c0506c9b26 100644 --- a/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts +++ b/packages/kbn-securitysolution-list-hooks/src/mocks/response/list_schema.mock.ts @@ -23,6 +23,7 @@ import { } from '../constants.mock'; export const getListResponseMock = (): ListSchema => ({ + '@timestamp': DATE_NOW, _version: undefined, created_at: DATE_NOW, created_by: USER, 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-telemetry-tools/src/tools/ts_program/ts_program.test.ts b/packages/kbn-telemetry-tools/src/tools/ts_program/ts_program.test.ts index 8ae36ea7330cc..7e15de907e31a 100644 --- a/packages/kbn-telemetry-tools/src/tools/ts_program/ts_program.test.ts +++ b/packages/kbn-telemetry-tools/src/tools/ts_program/ts_program.test.ts @@ -21,7 +21,7 @@ describe('createKibanaProgram', () => { "fetch": Object { "typeDescriptor": Object { "locale": Object { - "kind": 149, + "kind": 150, "type": "StringKeyword", }, }, 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/packages/kbn-unified-data-table/__mocks__/table_context.ts b/packages/kbn-unified-data-table/__mocks__/table_context.ts new file mode 100644 index 0000000000000..4a4a75b0fa9e5 --- /dev/null +++ b/packages/kbn-unified-data-table/__mocks__/table_context.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { 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 { 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 buildTableContext = (dataView: DataView, rows: EsHitRecord[]): DataTableContext => { + const usedRows = rows.map((row) => { + return buildDataTableRecord(row, dataView); + }); + + return { + expanded: undefined, + setExpanded: jest.fn(), + rows: usedRows, + onFilter: jest.fn(), + dataView, + isDarkMode: false, + selectedDocs: [], + setSelectedDocs: jest.fn(), + valueToStringConverter: (rowIndex, columnId, options) => + convertValueToString({ + rowIndex, + columnId, + fieldFormats: servicesMock.fieldFormats, + rows: usedRows, + dataView, + options, + }), + }; +}; + +export const dataTableContextMock = buildTableContext(dataViewMock, esHitsMock); + +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/packages/kbn-unified-data-table/src/components/actions/columns.test.ts b/packages/kbn-unified-data-table/src/components/actions/columns.test.ts new file mode 100644 index 0000000000000..d8480cf2067b4 --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/actions/columns.test.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { getStateColumnActions } from './columns'; +import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; +import { Capabilities } from '@kbn/core/types'; +import { dataViewsMock } from '../../../__mocks__/data_views'; + +function getStateColumnAction( + state: { columns?: string[]; sort?: string[][] }, + setAppState: (state: { columns: string[]; sort?: string[][] }) => void +) { + return getStateColumnActions({ + capabilities: { + discover: { + save: false, + }, + } as unknown as Capabilities, + dataView: dataViewMock, + dataViews: dataViewsMock, + useNewFieldsApi: true, + setAppState, + columns: state.columns, + sort: state.sort, + defaultOrder: 'desc', + }); +} + +describe('Test column actions', () => { + test('getStateColumnActions with empty state', () => { + const setAppState = jest.fn(); + const actions = getStateColumnAction({}, setAppState); + + actions.onAddColumn('_score'); + expect(setAppState).toHaveBeenCalledWith({ columns: ['_score'], sort: [['_score', 'desc']] }); + actions.onAddColumn('test'); + expect(setAppState).toHaveBeenCalledWith({ columns: ['test'] }); + }); + test('getStateColumnActions with columns and sort in state', () => { + const setAppState = jest.fn(); + const actions = getStateColumnAction( + { columns: ['first', 'second'], sort: [['first', 'desc']] }, + setAppState + ); + + actions.onAddColumn('_score'); + expect(setAppState).toHaveBeenCalledWith({ + columns: ['first', 'second', '_score'], + sort: [['first', 'desc']], + }); + setAppState.mockClear(); + actions.onAddColumn('third'); + expect(setAppState).toHaveBeenCalledWith({ + columns: ['first', 'second', 'third'], + sort: [['first', 'desc']], + }); + setAppState.mockClear(); + actions.onRemoveColumn('first'); + expect(setAppState).toHaveBeenCalledWith({ + columns: ['second'], + sort: [], + }); + setAppState.mockClear(); + actions.onSetColumns(['first', 'second', 'third'], true); + expect(setAppState).toHaveBeenCalledWith({ + columns: ['first', 'second', 'third'], + }); + setAppState.mockClear(); + + actions.onMoveColumn('second', 0); + expect(setAppState).toHaveBeenCalledWith({ + columns: ['second', 'first'], + }); + }); +}); diff --git a/packages/kbn-unified-data-table/src/components/actions/columns.ts b/packages/kbn-unified-data-table/src/components/actions/columns.ts new file mode 100644 index 0000000000000..3355902ece86e --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/actions/columns.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 and the Server Side Public License, v 1; you may 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 { 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 + * is empty, and removes _source if there are more than 1 columns given + * @param columns + * @param useNewFieldsApi should a new fields API be used + */ +function buildColumns(columns: string[], useNewFieldsApi = false) { + if (columns.length > 1 && columns.indexOf('_source') !== -1) { + return columns.filter((col) => col !== '_source'); + } else if (columns.length !== 0) { + return columns; + } + return useNewFieldsApi ? [] : ['_source']; +} + +export function addColumn(columns: string[], columnName: string, useNewFieldsApi?: boolean) { + if (columns.includes(columnName)) { + return columns; + } + return buildColumns([...columns, columnName], useNewFieldsApi); +} + +export function removeColumn(columns: string[], columnName: string, useNewFieldsApi?: boolean) { + if (!columns.includes(columnName)) { + return columns; + } + return buildColumns( + columns.filter((col) => col !== columnName), + useNewFieldsApi + ); +} + +export function moveColumn(columns: string[], columnName: string, newIndex: number) { + if (newIndex < 0 || newIndex >= columns.length || !columns.includes(columnName)) { + return columns; + } + const modifiedColumns = [...columns]; + modifiedColumns.splice(modifiedColumns.indexOf(columnName), 1); // remove at old index + modifiedColumns.splice(newIndex, 0, columnName); // insert before new index + return modifiedColumns; +} + +export function getStateColumnActions({ + capabilities, + dataView, + dataViews, + useNewFieldsApi, + setAppState, + columns, + sort, + defaultOrder, +}: { + capabilities: Capabilities; + dataView: DataView; + dataViews: DataViewsContract; + useNewFieldsApi: boolean; + 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 nextSort = columnName === '_score' && !sort?.length ? [['_score', defaultOrder]] : sort; + setAppState({ columns: nextColumns, sort: nextSort }); + } + + function onRemoveColumn(columnName: string) { + popularizeField(dataView, columnName, dataViews, capabilities); + const nextColumns = removeColumn(columns || [], columnName, useNewFieldsApi); + // The state's sort property is an array of [sortByColumn,sortDirection] + const nextSort = sort && sort.length ? sort.filter((subArr) => subArr[0] !== columnName) : []; + setAppState({ columns: nextColumns, sort: nextSort }); + } + + function onMoveColumn(columnName: string, newIndex: number) { + const nextColumns = moveColumn(columns || [], columnName, newIndex); + setAppState({ columns: nextColumns }); + } + + function onSetColumns(nextColumns: string[], hideTimeColumn: boolean) { + // The next line should be gone when classic table will be removed + const actualColumns = + !hideTimeColumn && dataView.timeFieldName && dataView.timeFieldName === nextColumns[0] + ? (nextColumns || []).slice(1) + : nextColumns; + + setAppState({ columns: actualColumns }); + } + return { + onAddColumn, + onRemoveColumn, + onMoveColumn, + onSetColumns, + }; +} 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/packages/kbn-unified-data-table/src/components/data_table.scss b/packages/kbn-unified-data-table/src/components/data_table.scss new file mode 100644 index 0000000000000..8b0f8719a450f --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table.scss @@ -0,0 +1,146 @@ +.unifiedDataTable { + width: 100%; + max-width: 100%; + height: 100%; + overflow: hidden; + border-radius: $euiBorderRadius; + + .euiDataGrid__controls { + border: none; + border-bottom: $euiBorderThin; + } + + .euiDataGridRowCell.euiDataGridRowCell--firstColumn { + border-left: none; + padding: 0; + } + + .euiDataGridRowCell.euiDataGridRowCell--lastColumn { + border-right: none; + } + + .unifiedDataTable__table .euiDataGridRowCell:first-of-type, + .unifiedDataTable__table .euiDataGrid--headerShade.euiDataGrid--bordersAll .euiDataGridHeaderCell:first-of-type { + border-left: none; + border-right: none; + } + + .euiDataGridRowCell:last-of-type, + .euiDataGridHeaderCell:last-of-type { + border-right: none; + } +} + +.unifiedDataTable__cellValue { + font-family: $euiCodeFontFamily; +} + +.unifiedDataTable__cellPopover { + // Fixes https://github.com/elastic/kibana/issues/145216 in Chrome + .lines-content.monaco-editor-background { + overflow: unset !important; + contain: unset !important; + } +} + +.unifiedDataTable__cellPopoverValue { + font-family: $euiCodeFontFamily; + font-size: $euiFontSizeS; +} + +.euiDataGridRowCell__definedHeight { + white-space: pre-wrap; +} + +.unifiedDataTable__inner { + display: flex; + flex-direction: column; + flex-wrap: nowrap; + height: 100%; +} + +.unifiedDataTable__table { + flex-grow: 1; + flex-shrink: 1; + min-height: 0; +} + +.unifiedDataTable__footer { + flex-shrink: 0; + background-color: $euiColorLightShade; + padding: $euiSize / 2 $euiSize; + margin-top: $euiSize / 4; + text-align: center; +} + +.unifiedDataTable__flyoutHeader { + white-space: nowrap; +} + +.unifiedDataTable__flyoutDocumentNavigation { + justify-content: flex-end; +} + +// We only truncate if the cell is not a control column. +.euiDataGridHeader { + + .euiDataGridHeaderCell__content { + @include euiTextTruncate; + overflow: hidden; + white-space: pre-wrap; + flex-grow: 1; + } + + .euiDataGridHeaderCell__popover { + flex-grow: 0; + flex-basis: auto; + width: auto; + padding-left: $euiSizeXS; + } +} + +.euiDataGridRowCell--numeric { + text-align: right; +} + +.euiDataGrid__loading, +.euiDataGrid__noResults { + display: flex; + flex-direction: column; + justify-content: center; + flex: 1 0 100%; + text-align: center; + height: 100%; + width: 100%; +} + +.unifiedDataTableFormatSource { + @include euiTextTruncate; +} + +.unifiedDataTable__descriptionListDescription { + word-break: break-all; + white-space: normal; + + // Special handling for images coming from the image field formatter + img { + // Align the images vertically centered with the text + vertical-align: middle; + // Set the maximum height to the line-height. The used function is the same + // function used to calculate the line-height for the EuiDescriptionList Description. + // !important is required to overwrite the max-height on the element from the field formatter + max-height: lineHeightFromBaseline(2) !important; + // An arbitrary amount of width we don't want to go over, to not have very wide images. + // For most width-height-ratios that will never be hit, because we'd usually limit + // it by the way smaller height. But images with very large width and very small height + // might be limited by that. + max-width: ($euiSizeXXL * 12.5) !important; + } +} + +@include euiBreakpoint('xs', 's', 'm') { + // EUI issue to hide 'of' text https://github.com/elastic/eui/issues/4654 + .unifiedDataTable__flyoutDocumentNavigation .euiPagination__compressedText { + display: none; + } +} diff --git a/packages/kbn-unified-data-table/src/components/data_table.test.tsx b/packages/kbn-unified-data-table/src/components/data_table.test.tsx new file mode 100644 index 0000000000000..7ca0888230749 --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table.test.tsx @@ -0,0 +1,435 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { ReactWrapper } from 'enzyme'; +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 { DataLoadingState, UnifiedDataTable, UnifiedDataTableProps } from './data_table'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { servicesMock } from '../../__mocks__/services'; +import { buildDataTableRecord, getDocId } from '@kbn/discover-utils'; +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', () => ({ + ...jest.requireActual('@kbn/cell-actions'), + useDataGridColumnsCellActions: (prop: unknown) => mockUseDataGridColumnsCellActions(prop), +})); + +export const dataViewMock = buildDataViewMock({ + name: 'the-data-view', + fields: deepMockedFields, + timeFieldName: '@timestamp', +}); + +function getProps(): UnifiedDataTableProps { + const services = servicesMock; + services.dataViewFieldEditor.userPermissions.editIndexPattern = jest.fn().mockReturnValue(true); + + return { + ariaLabelledBy: '', + columns: [], + dataView: dataViewMock, + loadingState: DataLoadingState.loaded, + expandedDoc: undefined, + onFilter: jest.fn(), + onResize: jest.fn(), + onSetColumns: jest.fn(), + onSort: jest.fn(), + rows: esHitsMock.map((hit) => buildDataTableRecord(hit, dataViewMock)), + sampleSize: 30, + searchDescription: '', + searchTitle: '', + setExpandedDoc: jest.fn(), + settings: {}, + showTimeCol: true, + sort: [], + useNewFieldsApi: true, + 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: UnifiedDataTableProps = getProps()) { + const Proxy = (innerProps: UnifiedDataTableProps) => ( + + + + ); + + const component = mountWithIntl(); + await act(async () => { + // needed by cell actions to complete async loading + component.update(); + }); + return component; +} + +function getSelectedDocNr(component: ReactWrapper) { + const gridSelectionBtn = findTestSubject(component, 'dscGridSelectionBtn'); + if (!gridSelectionBtn.length) { + return 0; + } + const selectedNr = gridSelectionBtn.getDOMNode().getAttribute('data-selected-documents'); + return Number(selectedNr); +} + +function getDisplayedDocNr(component: ReactWrapper) { + const gridSelectionBtn = findTestSubject(component, 'discoverDocTable'); + if (!gridSelectionBtn.length) { + return 0; + } + const selectedNr = gridSelectionBtn.getDOMNode().getAttribute('data-document-number'); + return Number(selectedNr); +} + +async function toggleDocSelection( + component: ReactWrapper, + document: EsHitRecord +) { + act(() => { + const docId = getDocId(document); + findTestSubject(component, `dscGridSelectDoc-${docId}`).simulate('change'); + }); + component.update(); +} + +describe('UnifiedDataTable', () => { + afterEach(async () => { + jest.clearAllMocks(); + }); + + describe('Document selection', () => { + let component: ReactWrapper; + beforeEach(async () => { + component = await getComponent(); + }); + + test('no documents are selected initially', async () => { + expect(getSelectedDocNr(component)).toBe(0); + expect(getDisplayedDocNr(component)).toBe(5); + }); + + test('Allows selection/deselection of multiple documents', async () => { + await toggleDocSelection(component, esHitsMock[0]); + expect(getSelectedDocNr(component)).toBe(1); + await toggleDocSelection(component, esHitsMock[1]); + expect(getSelectedDocNr(component)).toBe(2); + await toggleDocSelection(component, esHitsMock[1]); + expect(getSelectedDocNr(component)).toBe(1); + }); + + test('deselection of all selected documents', async () => { + await toggleDocSelection(component, esHitsMock[0]); + await toggleDocSelection(component, esHitsMock[1]); + expect(getSelectedDocNr(component)).toBe(2); + findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); + findTestSubject(component, 'dscGridClearSelectedDocuments').simulate('click'); + expect(getSelectedDocNr(component)).toBe(0); + }); + + test('showing only selected documents and undo selection', async () => { + await toggleDocSelection(component, esHitsMock[0]); + await toggleDocSelection(component, esHitsMock[1]); + expect(getSelectedDocNr(component)).toBe(2); + findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); + findTestSubject(component, 'dscGridShowSelectedDocuments').simulate('click'); + expect(getDisplayedDocNr(component)).toBe(2); + findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); + component.update(); + findTestSubject(component, 'dscGridShowAllDocuments').simulate('click'); + expect(getDisplayedDocNr(component)).toBe(5); + }); + + test('showing selected documents, underlying data changes, all documents are displayed, selection is gone', async () => { + await toggleDocSelection(component, esHitsMock[0]); + await toggleDocSelection(component, esHitsMock[1]); + expect(getSelectedDocNr(component)).toBe(2); + findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); + findTestSubject(component, 'dscGridShowSelectedDocuments').simulate('click'); + expect(getDisplayedDocNr(component)).toBe(2); + component.setProps({ + rows: [ + { + _index: 'i', + _id: '6', + _score: 1, + _source: { + date: '2020-20-02T12:12:12.128', + name: 'test6', + extension: 'doc', + bytes: 50, + }, + }, + ].map((row) => buildDataTableRecord(row, dataViewMock)), + }); + expect(getDisplayedDocNr(component)).toBe(1); + expect(getSelectedDocNr(component)).toBe(0); + }); + + test('showing only selected documents and remove filter deselecting each doc manually', async () => { + await toggleDocSelection(component, esHitsMock[0]); + findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); + findTestSubject(component, 'dscGridShowSelectedDocuments').simulate('click'); + expect(getDisplayedDocNr(component)).toBe(1); + await toggleDocSelection(component, esHitsMock[0]); + expect(getDisplayedDocNr(component)).toBe(5); + await toggleDocSelection(component, esHitsMock[0]); + expect(getDisplayedDocNr(component)).toBe(5); + }); + + test('copying selected documents to clipboard', async () => { + await toggleDocSelection(component, esHitsMock[0]); + findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); + expect(component.find(EuiCopy).prop('textToCopy')).toMatchInlineSnapshot( + `"[{\\"_index\\":\\"i\\",\\"_id\\":\\"1\\",\\"_score\\":1,\\"_type\\":\\"_doc\\",\\"_source\\":{\\"date\\":\\"2020-20-01T12:12:12.123\\",\\"message\\":\\"test1\\",\\"bytes\\":20}}]"` + ); + }); + }); + + describe('edit field button', () => { + it('should render the edit field button if onFieldEdited is provided', async () => { + const component = await getComponent({ + ...getProps(), + columns: ['message'], + onFieldEdited: jest.fn(), + }); + expect(findTestSubject(component, 'dataGridHeaderCellActionGroup-message').exists()).toBe( + false + ); + findTestSubject(component, 'dataGridHeaderCell-message').find('button').simulate('click'); + expect(findTestSubject(component, 'dataGridHeaderCellActionGroup-message').exists()).toBe( + true + ); + expect(findTestSubject(component, 'gridEditFieldButton').exists()).toBe(true); + }); + + it('should not render the edit field button if onFieldEdited is not provided', async () => { + const component = await getComponent({ + ...getProps(), + columns: ['message'], + }); + expect(findTestSubject(component, 'dataGridHeaderCellActionGroup-message').exists()).toBe( + false + ); + findTestSubject(component, 'dataGridHeaderCell-message').find('button').simulate('click'); + expect(findTestSubject(component, 'dataGridHeaderCellActionGroup-message').exists()).toBe( + true + ); + expect(findTestSubject(component, 'gridEditFieldButton').exists()).toBe(false); + }); + }); + + describe('cellActionsTriggerId', () => { + it('should call useDataGridColumnsCellActions with empty params when no cellActionsTriggerId is provided', async () => { + await getComponent({ + ...getProps(), + columns: ['message'], + onFieldEdited: jest.fn(), + }); + expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith( + expect.objectContaining({ + triggerId: undefined, + getCellValue: expect.any(Function), + fields: undefined, + }) + ); + }); + + it('should call useDataGridColumnsCellActions properly when cellActionsTriggerId defined', async () => { + await getComponent({ + ...getProps(), + columns: ['message'], + onFieldEdited: jest.fn(), + cellActionsTriggerId: 'test', + }); + expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith( + expect.objectContaining({ + triggerId: 'test', + getCellValue: expect.any(Function), + fields: [ + dataViewMock.getFieldByName('@timestamp')?.toSpec(), + dataViewMock.getFieldByName('message')?.toSpec(), + ], + }) + ); + }); + }); + + describe('sorting', () => { + it('should enable in memory sorting with plain records', async () => { + const component = await getComponent({ + ...getProps(), + columns: ['message'], + isPlainRecord: true, + }); + + expect( + ( + findTestSubject(component, 'docTable') + .find('EuiDataGridInMemoryRenderer') + .first() + .props() as Record + ).inMemory + ).toMatchInlineSnapshot(` + Object { + "level": "sorting", + } + `); + }); + }); + + 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/packages/kbn-unified-data-table/src/components/data_table.tsx b/packages/kbn-unified-data-table/src/components/data_table.tsx new file mode 100644 index 0000000000000..e5f5e5dbbba39 --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table.tsx @@ -0,0 +1,836 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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, { useCallback, useMemo, useState, useRef, useEffect } from 'react'; +import classnames from 'classnames'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { of } from 'rxjs'; +import useObservable from 'react-use/lib/useObservable'; +import './data_table.scss'; +import type { Storage } from '@kbn/kibana-utils-plugin/public'; +import { + EuiDataGridSorting, + EuiDataGrid, + EuiScreenReaderOnly, + EuiSpacer, + EuiText, + htmlIdGenerator, + EuiLoadingSpinner, + EuiIcon, + EuiDataGridRefProps, + EuiDataGridInMemory, + EuiDataGridControlColumn, + EuiDataGridCustomBodyProps, + EuiDataGridCellValueElementProps, +} from '@elastic/eui'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import { + useDataGridColumnsCellActions, + type UseDataGridColumnsCellActionsProps, +} from '@kbn/cell-actions'; +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, 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 { + 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', + loadingMore = 'loadingMore', + loaded = 'loaded', +} + +const themeDefault = { darkMode: false }; + +interface SortObj { + id: string; + direction: string; +} + +export interface UnifiedDataTableProps { + /** + * Determines which element labels the grid for ARIA + */ + ariaLabelledBy: string; + /** + * Optional class name to apply + */ + className?: string; + /** + * Determines ids of the columns which are displayed + */ + columns: string[]; + /** + * If set, the given document is displayed in a flyout + */ + expandedDoc?: DataTableRecord; + /** + * The used data view + */ + dataView: DataView; + /** + * Determines if data is currently loaded + */ + loadingState: DataLoadingState; + /** + * Function to add a filter in the grid cell or document flyout + */ + onFilter: DocViewFilterFn; + /** + * Function triggered when a column is resized by the user + */ + onResize?: (colSettings: { columnId: string; width: number }) => void; + /** + * Function to set all columns + */ + onSetColumns: (columns: string[], hideTimeColumn: boolean) => void; + /** + * function to change sorting of the documents, skipped when isSortEnabled is set to false + */ + onSort?: (sort: string[][]) => void; + /** + * Array of documents provided by Elasticsearch + */ + rows?: DataTableRecord[]; + /** + * The max size of the documents returned by Elasticsearch + */ + sampleSize: number; + /** + * Function to set the expanded document, which is displayed in a flyout + */ + setExpandedDoc?: (doc?: DataTableRecord) => void; + /** + * Grid display settings persisted in Elasticsearch (e.g. column width) + */ + settings?: UnifiedDataTableSettings; + /** + * Search description + */ + searchDescription?: string; + /** + * Search title + */ + searchTitle?: string; + /** + * Determines whether the time columns should be displayed (legacy settings) + */ + showTimeCol: boolean; + /** + * Determines whether the full screen button should be displayed + */ + showFullScreenButton?: boolean; + /** + * Manage user sorting control + */ + isSortEnabled?: boolean; + /** + * Current sort setting + */ + sort: SortOrder[]; + /** + * How the data is fetched + */ + useNewFieldsApi: boolean; + /** + * Manage pagination control + */ + isPaginationEnabled?: boolean; + /** + * List of used control columns (available: 'openDetails', 'select') + */ + controlColumnIds?: string[]; + /** + * Row height from state + */ + rowHeightState?: number; + /** + * Update row height state + */ + onUpdateRowHeight?: (rowHeight: number) => void; + /** + * Is text base lang mode enabled + */ + isPlainRecord?: boolean; + /** + * Current state value for rowsPerPage + */ + rowsPerPageState?: number; + /** + * Update rows per page state + */ + onUpdateRowsPerPage?: (rowsPerPage: number) => void; + /** + * Callback to execute on edit runtime field + */ + onFieldEdited?: () => void; + /** + * Optional triggerId to retrieve the column cell actions that will override the default ones + */ + cellActionsTriggerId?: string; + /** + * Service dependencies + */ + services: { + theme: ThemeServiceStart; + fieldFormats: FieldFormatsStart; + 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 + */ + totalHits?: number; + /** + * 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 UnifiedDataTable = ({ + ariaLabelledBy, + columns, + controlColumnIds = CONTROL_COLUMN_IDS_DEFAULT, + dataView, + loadingState, + onFilter, + onResize, + onSetColumns, + onSort, + rows, + sampleSize, + searchDescription, + searchTitle, + settings, + showTimeCol, + showFullScreenButton = true, + sort, + useNewFieldsApi, + isSortEnabled = true, + isPaginationEnabled = true, + cellActionsTriggerId, + className, + rowHeightState, + onUpdateRowHeight, + isPlainRecord = false, + rowsPerPageState, + onUpdateRowsPerPage, + onFieldEdited, + services, + renderCustomGridBody, + trailingControlColumns, + totalHits, + onFetchMoreRecords, + 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); + const displayedColumns = getDisplayedColumns(columns, dataView); + const defaultColumns = displayedColumns.includes('_source'); + const usedSelectedDocs = useMemo(() => { + if (!selectedDocs.length || !rows?.length) { + return []; + } + 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)); + if (result.length === 0 && isFilterActive) { + setIsFilterActive(false); + } + return result; + }, [selectedDocs, rows, isFilterActive]); + + const displayedRows = useMemo(() => { + if (!rows) { + return []; + } + if (!isFilterActive || usedSelectedDocs.length === 0) { + return rows; + } + const rowsFiltered = rows.filter((row) => usedSelectedDocs.includes(row.id)); + if (!rowsFiltered.length) { + // in case the selected docs are no longer part of the sample of 500, show all docs + return rows; + } + return rowsFiltered; + }, [rows, usedSelectedDocs, isFilterActive]); + + const valueToStringConverter: ValueToStringConverter = useCallback( + (rowIndex, columnId, options) => { + return convertValueToString({ + rowIndex, + rows: displayedRows, + dataView, + columnId, + fieldFormats, + options, + }); + }, + [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 currentPageSize = + typeof rowsPerPageState === 'number' && rowsPerPageState > 0 + ? rowsPerPageState + : DEFAULT_ROWS_PER_PAGE; + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: currentPageSize, + }); + const rowCount = useMemo(() => (displayedRows ? displayedRows.length : 0), [displayedRows]); + const pageCount = useMemo( + () => Math.ceil(rowCount / pagination.pageSize), + [rowCount, pagination] + ); + + const paginationObj = useMemo(() => { + const onChangeItemsPerPage = (pageSize: number) => { + onUpdateRowsPerPage?.(pageSize); + }; + + const onChangePage = (pageIndex: number) => + setPagination((paginationData) => ({ ...paginationData, pageIndex })); + + return isPaginationEnabled + ? { + onChangeItemsPerPage, + onChangePage, + pageIndex: pagination.pageIndex > pageCount - 1 ? 0 : pagination.pageIndex, + pageSize: pagination.pageSize, + pageSizeOptions: rowsPerPageOptions ?? getRowsPerPageOptions(pagination.pageSize), + } + : undefined; + }, [ + isPaginationEnabled, + pagination.pageIndex, + pagination.pageSize, + pageCount, + rowsPerPageOptions, + onUpdateRowsPerPage, + ]); + + useEffect(() => { + setPagination((paginationData) => + paginationData.pageSize === currentPageSize + ? paginationData + : { ...paginationData, pageSize: currentPageSize } + ); + }, [currentPageSize, setPagination]); + + /** + * Sorting + */ + const sortingColumns = useMemo(() => sort.map(([id, direction]) => ({ id, direction })), [sort]); + + const [inmemorySortingColumns, setInmemorySortingColumns] = useState([]); + const onTableSort = useCallback( + (sortingColumnsData) => { + if (isSortEnabled) { + if (isPlainRecord) { + setInmemorySortingColumns(sortingColumnsData); + } else if (onSort) { + onSort(sortingColumnsData.map(({ id, direction }: SortObj) => [id, direction])); + } + } + }, + [onSort, isSortEnabled, isPlainRecord, setInmemorySortingColumns] + ); + + const shouldShowFieldHandler = useMemo(() => { + const dataViewFields = dataView.fields.getAll().map((fld) => fld.name); + return getShouldShowFieldHandler(dataViewFields, dataView, showMultiFields); + }, [dataView, showMultiFields]); + + /** + * Cell rendering + */ + const renderCellValue = useMemo( + () => + getRenderCellValueFn( + dataView, + displayedRows, + useNewFieldsApi, + shouldShowFieldHandler, + () => dataGridRef.current?.closeCellPopover(), + services.fieldFormats, + maxDocFieldsDisplayed, + externalCustomRenderers + ), + [ + dataView, + displayedRows, + useNewFieldsApi, + shouldShowFieldHandler, + maxDocFieldsDisplayed, + services.fieldFormats, + externalCustomRenderers, + ] + ); + + /** + * Render variables + */ + const randomId = useMemo(() => htmlIdGenerator()(), []); + const closeFieldEditor = useRef<() => void | undefined>(); + + useEffect(() => { + return () => { + if (closeFieldEditor?.current) { + closeFieldEditor?.current(); + } + }; + }, []); + + const editField = useMemo( + () => + onFieldEdited + ? (fieldName: string) => { + closeFieldEditor.current = services.dataViewFieldEditor.openEditor({ + ctx: { + dataView, + }, + fieldName, + onSave: async () => { + await onFieldEdited(); + }, + }); + } + : undefined, + [dataView, onFieldEdited, services.dataViewFieldEditor] + ); + + const visibleColumns = useMemo( + () => getVisibleColumns(displayedColumns, dataView, showTimeCol), + [dataView, displayedColumns, showTimeCol] + ); + + const getCellValue = useCallback( + (fieldName, rowIndex) => + displayedRows[rowIndex % displayedRows.length].flattened[fieldName] as Serializable, + [displayedRows] + ); + + const cellActionsFields = useMemo( + () => + cellActionsTriggerId && !isPlainRecord + ? visibleColumns.map( + (columnName) => + dataView.getFieldByName(columnName)?.toSpec() ?? { + name: '', + type: '', + aggregatable: false, + searchable: false, + } + ) + : undefined, + [cellActionsTriggerId, isPlainRecord, visibleColumns, dataView] + ); + + const columnsCellActions = useDataGridColumnsCellActions({ + fields: cellActionsFields, + getCellValue, + triggerId: cellActionsTriggerId, + dataGridRef, + }); + + const euiGridColumns = useMemo( + () => + getEuiGridColumns({ + columns: visibleColumns, + columnsCellActions, + rowsCount: displayedRows.length, + settings, + dataView, + defaultColumns, + isSortEnabled, + isPlainRecord, + services: { + uiSettings, + toastNotifications, + }, + hasEditDataViewPermission: () => dataViewFieldEditor.userPermissions.editIndexPattern(), + valueToStringConverter, + onFilter, + editField, + visibleCellActions, + }), + [ + onFilter, + visibleColumns, + columnsCellActions, + displayedRows, + dataView, + settings, + defaultColumns, + isSortEnabled, + isPlainRecord, + uiSettings, + toastNotifications, + dataViewFieldEditor, + valueToStringConverter, + editField, + visibleCellActions, + ] + ); + + const hideTimeColumn = useMemo( + () => services.uiSettings.get(DOC_HIDE_TIME_COLUMN_SETTING, false), + [services.uiSettings] + ); + const schemaDetectors = useMemo(() => getSchemaDetectors(), []); + const columnsVisibility = useMemo( + () => ({ + visibleColumns, + setVisibleColumns: (newColumns: string[]) => { + onSetColumns(newColumns, hideTimeColumn); + }, + }), + [visibleColumns, hideTimeColumn, onSetColumns] + ); + const sorting = useMemo(() => { + if (isSortEnabled) { + return { + columns: isPlainRecord ? inmemorySortingColumns : sortingColumns, + onSort: onTableSort, + }; + } + return { columns: sortingColumns, onSort: () => {} }; + }, [isSortEnabled, sortingColumns, isPlainRecord, inmemorySortingColumns, onTableSort]); + + const canSetExpandedDoc = Boolean(setExpandedDoc && !!renderDocumentView); + + 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} + {externalAdditionalControls} + + ), + [usedSelectedDocs, isFilterActive, rows, externalAdditionalControls] + ); + + const showDisplaySelector = useMemo( + () => + !!onUpdateRowHeight + ? { + allowDensity: false, + allowRowHeight: true, + } + : undefined, + [onUpdateRowHeight] + ); + + const inMemory = useMemo(() => { + return isPlainRecord && columns.length + ? ({ level: 'sorting' } as EuiDataGridInMemory) + : undefined; + }, [columns.length, isPlainRecord]); + + const toolbarVisibility = useMemo( + () => + defaultColumns + ? { + ...toolbarVisibilityDefaults, + showColumnSelector: false, + showSortSelector: isSortEnabled, + additionalControls, + showDisplaySelector, + showFullScreenSelector: showFullScreenButton, + } + : { + ...toolbarVisibilityDefaults, + showSortSelector: isSortEnabled, + additionalControls, + showDisplaySelector, + showFullScreenSelector: showFullScreenButton, + }, + [defaultColumns, isSortEnabled, additionalControls, showDisplaySelector, showFullScreenButton] + ); + + const rowHeightsOptions = useRowHeightsOptions({ + rowHeightState, + onUpdateRowHeight, + storage, + configRowHeight, + consumer, + }); + + const isRenderComplete = loadingState !== DataLoadingState.loading; + + if (!rowCount && loadingState === DataLoadingState.loading) { + return ( +
    + + + + + +
    + ); + } + + if (!rowCount) { + return ( +
    + + + + + +
    + ); + } + + return ( + + +
    + +
    + {loadingState !== DataLoadingState.loading && + isPaginationEnabled && ( // we hide the footer for Surrounding Documents page + + )} + {searchTitle && ( + +

    + {searchDescription ? ( + + ) : ( + + )} +

    +
    + )} + {canSetExpandedDoc && + expandedDoc && + renderDocumentView!(expandedDoc, displayedRows, displayedColumns)} +
    +
    + ); +}; diff --git a/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx b/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx new file mode 100644 index 0000000000000..01246603643fd --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx @@ -0,0 +1,541 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; +import { getEuiGridColumns, getVisibleColumns } from './data_table_columns'; +import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; +import { dataTableContextMock } from '../../__mocks__/table_context'; +import { servicesMock } from '../../__mocks__/services'; + +const columns = ['extension', 'message']; +const columnsWithTimeCol = getVisibleColumns( + ['extension', 'message'], + dataViewWithTimefieldMock, + true +) as string[]; + +describe('Data table columns', function () { + describe('getEuiGridColumns', () => { + it('returns eui grid columns showing default columns', async () => { + const actual = getEuiGridColumns({ + columns, + settings: {}, + dataView: dataViewWithTimefieldMock, + defaultColumns: true, + isSortEnabled: true, + isPlainRecord: false, + valueToStringConverter: dataTableContextMock.valueToStringConverter, + rowsCount: 100, + services: { + uiSettings: servicesMock.uiSettings, + toastNotifications: servicesMock.toastNotifications, + }, + hasEditDataViewPermission: () => + servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(), + onFilter: () => {}, + }); + expect(actual).toMatchInlineSnapshot(` + Array [ + Object { + "actions": Object { + "additional": Array [ + Object { + "data-test-subj": "gridCopyColumnNameToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + Object { + "data-test-subj": "gridCopyColumnValuesToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + ], + "showHide": false, + "showMoveLeft": false, + "showMoveRight": false, + }, + "cellActions": Array [ + [Function], + [Function], + [Function], + ], + "displayAsText": "extension", + "id": "extension", + "isSortable": false, + "schema": "string", + "visibleCellActions": undefined, + }, + Object { + "actions": Object { + "additional": Array [ + Object { + "data-test-subj": "gridCopyColumnNameToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + Object { + "data-test-subj": "gridCopyColumnValuesToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + ], + "showHide": false, + "showMoveLeft": false, + "showMoveRight": false, + }, + "cellActions": Array [ + [Function], + ], + "displayAsText": "message", + "id": "message", + "isSortable": false, + "schema": "string", + "visibleCellActions": undefined, + }, + ] + `); + }); + + it('returns eui grid columns with time column', async () => { + const actual = getEuiGridColumns({ + columns: columnsWithTimeCol, + settings: {}, + dataView: dataViewWithTimefieldMock, + defaultColumns: false, + isSortEnabled: true, + isPlainRecord: false, + valueToStringConverter: dataTableContextMock.valueToStringConverter, + rowsCount: 100, + services: { + uiSettings: servicesMock.uiSettings, + toastNotifications: servicesMock.toastNotifications, + }, + hasEditDataViewPermission: () => + servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(), + onFilter: () => {}, + }); + expect(actual).toMatchInlineSnapshot(` + Array [ + Object { + "actions": Object { + "additional": Array [ + Object { + "data-test-subj": "gridCopyColumnNameToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + Object { + "data-test-subj": "gridCopyColumnValuesToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + ], + "showHide": false, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": Array [ + [Function], + [Function], + [Function], + ], + "display":
    + + + timestamp + + + + +
    , + "displayAsText": "timestamp", + "id": "timestamp", + "initialWidth": 210, + "isSortable": true, + "schema": "datetime", + "visibleCellActions": undefined, + }, + Object { + "actions": Object { + "additional": Array [ + Object { + "data-test-subj": "gridCopyColumnNameToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + Object { + "data-test-subj": "gridCopyColumnValuesToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + ], + "showHide": Object { + "iconType": "cross", + "label": "Remove column", + }, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": Array [ + [Function], + [Function], + [Function], + ], + "displayAsText": "extension", + "id": "extension", + "isSortable": false, + "schema": "string", + "visibleCellActions": undefined, + }, + Object { + "actions": Object { + "additional": Array [ + Object { + "data-test-subj": "gridCopyColumnNameToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + Object { + "data-test-subj": "gridCopyColumnValuesToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + ], + "showHide": Object { + "iconType": "cross", + "label": "Remove column", + }, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": Array [ + [Function], + ], + "displayAsText": "message", + "id": "message", + "isSortable": false, + "schema": "string", + "visibleCellActions": undefined, + }, + ] + `); + }); + + it('returns eui grid with in memory sorting', async () => { + const actual = getEuiGridColumns({ + columns: columnsWithTimeCol, + settings: {}, + dataView: dataViewWithTimefieldMock, + defaultColumns: false, + isSortEnabled: true, + isPlainRecord: true, + valueToStringConverter: dataTableContextMock.valueToStringConverter, + rowsCount: 100, + services: { + uiSettings: servicesMock.uiSettings, + toastNotifications: servicesMock.toastNotifications, + }, + hasEditDataViewPermission: () => + servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(), + onFilter: () => {}, + }); + expect(actual).toMatchInlineSnapshot(` + Array [ + Object { + "actions": Object { + "additional": Array [ + Object { + "data-test-subj": "gridCopyColumnNameToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + Object { + "data-test-subj": "gridCopyColumnValuesToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + ], + "showHide": false, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": Array [ + [Function], + [Function], + [Function], + ], + "display":
    + + + timestamp + + + + +
    , + "displayAsText": "timestamp", + "id": "timestamp", + "initialWidth": 210, + "isSortable": true, + "schema": "datetime", + "visibleCellActions": undefined, + }, + Object { + "actions": Object { + "additional": Array [ + Object { + "data-test-subj": "gridCopyColumnNameToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + Object { + "data-test-subj": "gridCopyColumnValuesToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + ], + "showHide": Object { + "iconType": "cross", + "label": "Remove column", + }, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": Array [ + [Function], + [Function], + [Function], + ], + "displayAsText": "extension", + "id": "extension", + "isSortable": true, + "schema": "string", + "visibleCellActions": undefined, + }, + Object { + "actions": Object { + "additional": Array [ + Object { + "data-test-subj": "gridCopyColumnNameToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + Object { + "data-test-subj": "gridCopyColumnValuesToClipBoardButton", + "iconProps": Object { + "size": "m", + }, + "iconType": "copyClipboard", + "label": , + "onClick": [Function], + "size": "xs", + }, + ], + "showHide": Object { + "iconType": "cross", + "label": "Remove column", + }, + "showMoveLeft": true, + "showMoveRight": true, + }, + "cellActions": Array [ + [Function], + ], + "displayAsText": "message", + "id": "message", + "isSortable": true, + "schema": "string", + "visibleCellActions": undefined, + }, + ] + `); + }); + }); + + describe('getVisibleColumns', () => { + it('returns grid columns without time column when data view has no timestamp field', () => { + const actual = getVisibleColumns(['extension', 'message'], dataViewMock, true) as string[]; + expect(actual).toEqual(['extension', 'message']); + }); + + it('returns grid columns without time column when showTimeCol is falsy', () => { + const actual = getVisibleColumns( + ['extension', 'message'], + dataViewWithTimefieldMock, + false + ) as string[]; + expect(actual).toEqual(['extension', 'message']); + }); + + it('returns grid columns with time column when data view has timestamp field', () => { + const actual = getVisibleColumns( + ['extension', 'message'], + dataViewWithTimefieldMock, + true + ) as string[]; + expect(actual).toEqual(['timestamp', 'extension', 'message']); + }); + }); +}); diff --git a/packages/kbn-unified-data-table/src/components/data_table_columns.tsx b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx new file mode 100644 index 0000000000000..4b66f2a2bd6cf --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx @@ -0,0 +1,255 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { + type EuiDataGridColumn, + type EuiDataGridColumnCellAction, + EuiIcon, + EuiScreenReaderOnly, + EuiToolTip, +} from '@elastic/eui'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import { ToastsStart, IUiSettingsClient } from '@kbn/core/public'; +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'; + +const openDetails = { + id: 'openDetails', + width: 24, + headerCellRender: () => ( + + + {i18n.translate('unifiedDataTable.controlColumnHeader', { + defaultMessage: 'Control column', + })} + + + ), + rowCellRender: ExpandButton, +}; + +const select = { + id: 'select', + width: 24, + rowCellRender: SelectButton, + headerCellRender: () => ( + + + {i18n.translate('unifiedDataTable.selectColumnHeader', { + defaultMessage: 'Select column', + })} + + + ), +}; + +export function getLeadControlColumns(canSetExpandedDoc: boolean) { + if (!canSetExpandedDoc) { + return [select]; + } + return [openDetails, select]; +} + +function buildEuiGridColumn({ + columnName, + columnWidth = 0, + dataView, + defaultColumns, + isSortEnabled, + isPlainRecord, + toastNotifications, + hasEditDataViewPermission, + valueToStringConverter, + rowsCount, + onFilter, + editField, + columnCellActions, + visibleCellActions, +}: { + columnName: string; + columnWidth: number | undefined; + dataView: DataView; + defaultColumns: boolean; + isSortEnabled: boolean; + isPlainRecord?: boolean; + toastNotifications: ToastsStart; + hasEditDataViewPermission: () => boolean; + valueToStringConverter: ValueToStringConverter; + rowsCount: number; + onFilter?: DocViewFilterFn; + editField?: (fieldName: string) => void; + columnCellActions?: EuiDataGridColumnCellAction[]; + visibleCellActions?: number; +}) { + const dataViewField = dataView.getFieldByName(columnName); + const editFieldButton = + editField && + dataViewField && + buildEditFieldButton({ hasEditDataViewPermission, dataView, field: dataViewField, editField }); + const columnDisplayName = + columnName === '_source' + ? i18n.translate('unifiedDataTable.grid.documentHeader', { + defaultMessage: 'Document', + }) + : dataViewField?.displayName || columnName; + + let cellActions: EuiDataGridColumnCellAction[]; + + if (columnCellActions?.length) { + cellActions = columnCellActions; + } else { + cellActions = dataViewField + ? buildCellActions(dataViewField, toastNotifications, valueToStringConverter, onFilter) + : []; + } + + const column: EuiDataGridColumn = { + id: columnName, + schema: getSchemaByKbnType(dataViewField?.type), + isSortable: isSortEnabled && (isPlainRecord || dataViewField?.sortable === true), + displayAsText: columnDisplayName, + actions: { + showHide: + defaultColumns || columnName === dataView.timeFieldName + ? false + : { + label: i18n.translate('unifiedDataTable.removeColumnLabel', { + defaultMessage: 'Remove column', + }), + iconType: 'cross', + }, + showMoveLeft: !defaultColumns, + showMoveRight: !defaultColumns, + additional: [ + ...(columnName === '__source' + ? [] + : [ + buildCopyColumnNameButton({ + columnDisplayName, + toastNotifications, + }), + ]), + buildCopyColumnValuesButton({ + columnId: columnName, + columnDisplayName, + toastNotifications, + rowsCount, + valueToStringConverter, + }), + ...(editFieldButton ? [editFieldButton] : []), + ], + }, + cellActions, + visibleCellActions, + }; + + if (column.id === dataView.timeFieldName) { + const timeFieldName = dataViewField?.customLabel ?? dataView.timeFieldName; + const primaryTimeAriaLabel = i18n.translate( + 'unifiedDataTable.tableHeader.timeFieldIconTooltipAriaLabel', + { + defaultMessage: '{timeFieldName} - this field represents the time that events occurred.', + values: { timeFieldName }, + } + ); + const primaryTimeTooltip = i18n.translate('unifiedDataTable.tableHeader.timeFieldIconTooltip', { + defaultMessage: 'This field represents the time that events occurred.', + }); + + column.display = ( +
    + + <> + {timeFieldName} + + +
    + ); + column.initialWidth = defaultTimeColumnWidth; + } + if (columnWidth > 0) { + column.initialWidth = Number(columnWidth); + } + return column; +} + +export function getEuiGridColumns({ + columns, + columnsCellActions, + rowsCount, + settings, + dataView, + defaultColumns, + isSortEnabled, + isPlainRecord, + services, + hasEditDataViewPermission, + valueToStringConverter, + onFilter, + editField, + visibleCellActions, +}: { + columns: string[]; + columnsCellActions?: EuiDataGridColumnCellAction[][]; + rowsCount: number; + settings: UnifiedDataTableSettings | undefined; + dataView: DataView; + defaultColumns: boolean; + isSortEnabled: boolean; + isPlainRecord?: boolean; + services: { + uiSettings: IUiSettingsClient; + toastNotifications: ToastsStart; + }; + hasEditDataViewPermission: () => boolean; + valueToStringConverter: ValueToStringConverter; + onFilter: DocViewFilterFn; + editField?: (fieldName: string) => void; + visibleCellActions?: number; +}) { + const getColWidth = (column: string) => settings?.columns?.[column]?.width ?? 0; + + return columns.map((column, columnIndex) => + buildEuiGridColumn({ + columnName: column, + columnCellActions: columnsCellActions?.[columnIndex], + columnWidth: getColWidth(column), + dataView, + defaultColumns, + isSortEnabled, + isPlainRecord, + toastNotifications: services.toastNotifications, + hasEditDataViewPermission, + valueToStringConverter, + rowsCount, + onFilter, + editField, + visibleCellActions, + }) + ); +} + +export function getVisibleColumns(columns: string[], dataView: DataView, showTimeCol: boolean) { + const timeFieldName = dataView.timeFieldName; + + if (showTimeCol && timeFieldName && !columns.find((col) => col === timeFieldName)) { + return [timeFieldName, ...columns]; + } + + return columns; +} diff --git a/packages/kbn-unified-data-table/src/components/data_table_document_selection.test.tsx b/packages/kbn-unified-data-table/src/components/data_table_document_selection.test.tsx new file mode 100644 index 0000000000000..ca0d422948416 --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table_document_selection.test.tsx @@ -0,0 +1,145 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { mountWithIntl } from '@kbn/test-jest-helpers'; +import { findTestSubject } from '@elastic/eui/lib/test'; +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', () => { + describe('getDocId', () => { + test('doc with custom routing', () => { + const doc = { + _id: 'test-id', + _index: 'test-indices', + _routing: 'why-not', + }; + expect(getDocId(doc)).toMatchInlineSnapshot(`"test-indices::test-id::why-not"`); + }); + test('doc without custom routing', () => { + const doc = { + _id: 'test-id', + _index: 'test-indices', + }; + expect(getDocId(doc)).toMatchInlineSnapshot(`"test-indices::test-id::"`); + }); + }); + + describe('SelectButton', () => { + test('is not checked', () => { + const contextMock = { + ...dataTableContextMock, + }; + + const component = mountWithIntl( + + + + ); + + const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); + expect(checkBox.props().checked).toBeFalsy(); + }); + + test('is checked', () => { + const contextMock = { + ...dataTableContextMock, + selectedDocs: ['i::1::'], + }; + + const component = mountWithIntl( + + + + ); + + const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); + expect(checkBox.props().checked).toBeTruthy(); + }); + + test('adding a selection', () => { + const contextMock = { + ...dataTableContextMock, + }; + + const component = mountWithIntl( + + + + ); + + const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); + checkBox.simulate('change'); + expect(contextMock.setSelectedDocs).toHaveBeenCalledWith(['i::1::']); + }); + test('removing a selection', () => { + const contextMock = { + ...dataTableContextMock, + selectedDocs: ['i::1::'], + }; + + const component = mountWithIntl( + + + + ); + + const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); + checkBox.simulate('change'); + expect(contextMock.setSelectedDocs).toHaveBeenCalledWith([]); + }); + }); + describe('DataTableDocumentToolbarBtn', () => { + test('it renders a button clickable button', () => { + const props = { + isFilterActive: false, + rows: dataTableContextMock.rows, + selectedDocs: ['i::1::'], + setIsFilterActive: jest.fn(), + setSelectedDocs: jest.fn(), + }; + const component = mountWithIntl(); + const button = findTestSubject(component, 'dscGridSelectionBtn'); + expect(button.length).toBe(1); + }); + }); +}); diff --git a/packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx b/packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx new file mode 100644 index 0000000000000..213e24790e840 --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table_document_selection.tsx @@ -0,0 +1,192 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; +import classNames from 'classnames'; +import { + EuiButtonEmpty, + EuiCheckbox, + EuiContextMenuItem, + EuiContextMenuPanel, + EuiCopy, + EuiDataGridCellValueElementProps, + EuiPopover, +} from '@elastic/eui'; +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 { UnifiedDataTableContext } from '../table_context'; + +export const SelectButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => { + const { selectedDocs, expanded, rows, isDarkMode, setSelectedDocs } = + useContext(UnifiedDataTableContext); + const doc = useMemo(() => rows[rowIndex], [rows, rowIndex]); + const checked = useMemo(() => selectedDocs.includes(doc.id), [selectedDocs, doc.id]); + + const toggleDocumentSelectionLabel = i18n.translate('unifiedDataTable.grid.selectDoc', { + defaultMessage: `Select document '{rowNumber}'`, + values: { rowNumber: rowIndex + 1 }, + }); + + useEffect(() => { + if (expanded && doc && expanded.id === doc.id) { + setCellProps({ + style: { + backgroundColor: isDarkMode ? themeDark.euiColorHighlight : themeLight.euiColorHighlight, + }, + }); + } else { + setCellProps({ style: undefined }); + } + }, [expanded, doc, setCellProps, isDarkMode]); + + return ( + { + if (checked) { + const newSelection = selectedDocs.filter((docId) => docId !== doc.id); + setSelectedDocs(newSelection); + } else { + setSelectedDocs([...selectedDocs, doc.id]); + } + }} + /> + ); +}; + +export function DataTableDocumentToolbarBtn({ + isFilterActive, + rows, + selectedDocs, + setIsFilterActive, + setSelectedDocs, +}: { + isFilterActive: boolean; + rows: DataTableRecord[]; + selectedDocs: string[]; + setIsFilterActive: (value: boolean) => void; + setSelectedDocs: (value: string[]) => void; +}) { + const [isSelectionPopoverOpen, setIsSelectionPopoverOpen] = useState(false); + + const getMenuItems = useCallback(() => { + return [ + isFilterActive ? ( + { + setIsSelectionPopoverOpen(false); + setIsFilterActive(false); + }} + > + + + ) : ( + { + setIsSelectionPopoverOpen(false); + setIsFilterActive(true); + }} + > + + + ), + selectedDocs.includes(row.id)).map((row) => row.raw) + ) + : '' + } + > + {(copy) => ( + + + + )} + , + { + setIsSelectionPopoverOpen(false); + setSelectedDocs([]); + setIsFilterActive(false); + }} + > + + , + ]; + }, [ + isFilterActive, + rows, + selectedDocs, + setIsFilterActive, + setIsSelectionPopoverOpen, + setSelectedDocs, + ]); + + const toggleSelectionToolbar = useCallback( + () => setIsSelectionPopoverOpen((prevIsOpen) => !prevIsOpen), + [] + ); + + return ( + setIsSelectionPopoverOpen(false)} + isOpen={isSelectionPopoverOpen} + panelPaddingSize="none" + button={ + + + + } + > + {isSelectionPopoverOpen && } + + ); +} diff --git a/packages/kbn-unified-data-table/src/components/data_table_expand_button.test.tsx b/packages/kbn-unified-data-table/src/components/data_table_expand_button.test.tsx new file mode 100644 index 0000000000000..56d6d3ae3ce0e --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table_expand_button.test.tsx @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { findTestSubject } from '@elastic/eui/lib/test'; +import { ExpandButton } from './data_table_expand_button'; +import { UnifiedDataTableContext } from '../table_context'; +import { dataTableContextMock } from '../../__mocks__/table_context'; + +describe('Data table view button ', function () { + it('when no document is expanded, setExpanded is called with current document', async () => { + const contextMock = { + ...dataTableContextMock, + }; + + const component = mountWithIntl( + + + + ); + const button = findTestSubject(component, 'docTableExpandToggleColumn'); + await button.simulate('click'); + expect(contextMock.setExpanded).toHaveBeenCalledWith(dataTableContextMock.rows[0]); + }); + it('when the current document is expanded, setExpanded is called with undefined', async () => { + const contextMock = { + ...dataTableContextMock, + expanded: dataTableContextMock.rows[0], + }; + + const component = mountWithIntl( + + + + ); + const button = findTestSubject(component, 'docTableExpandToggleColumn'); + await button.simulate('click'); + expect(contextMock.setExpanded).toHaveBeenCalledWith(undefined); + }); + it('when another document is expanded, setExpanded is called with the current document', async () => { + const contextMock = { + ...dataTableContextMock, + expanded: dataTableContextMock.rows[0], + }; + + const component = mountWithIntl( + + + + ); + const button = findTestSubject(component, 'docTableExpandToggleColumn'); + await button.simulate('click'); + expect(contextMock.setExpanded).toHaveBeenCalledWith(dataTableContextMock.rows[1]); + }); +}); diff --git a/packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx b/packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx new file mode 100644 index 0000000000000..108ffaa4ec5fe --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table_expand_button.tsx @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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, { 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 { UnifiedDataTableContext } from '../table_context'; + +/** + * Button to expand a given row + */ +export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => { + const toolTipRef = useRef(null); + const [pressed, setPressed] = useState(false); + const { expanded, setExpanded, rows, isDarkMode, componentsTourSteps } = + useContext(UnifiedDataTableContext); + const current = rows[rowIndex]; + + const tourStep = componentsTourSteps ? componentsTourSteps.expandButton : undefined; + useEffect(() => { + if (current.isAnchor) { + setCellProps({ + className: 'dscDocsGrid__cell--highlight', + }); + } else if (expanded && current && expanded.id === current.id) { + setCellProps({ + style: { + backgroundColor: isDarkMode ? themeDark.euiColorHighlight : themeLight.euiColorHighlight, + }, + }); + } else { + setCellProps({ style: undefined }); + } + }, [expanded, current, setCellProps, isDarkMode]); + + const isCurrentRowExpanded = current === expanded; + const buttonLabel = i18n.translate('unifiedDataTable.grid.viewDoc', { + defaultMessage: 'Toggle dialog with details', + }); + + const testSubj = current.isAnchor + ? 'docTableExpandToggleColumnAnchor' + : 'docTableExpandToggleColumn'; + + useEffect(() => { + if (!isCurrentRowExpanded && pressed) { + setPressed(false); + setTimeout(() => { + toolTipRef.current?.hideToolTip(); + }, 100); + } + }, [isCurrentRowExpanded, setPressed, pressed]); + + if (!setExpanded) { + return null; + } + + return ( + + { + const nextHit = isCurrentRowExpanded ? undefined : current; + toolTipRef.current?.hideToolTip(); + setPressed(Boolean(nextHit)); + setExpanded?.(nextHit); + }} + color={isCurrentRowExpanded ? 'primary' : 'text'} + iconType={isCurrentRowExpanded ? 'minimize' : 'expand'} + isSelected={isCurrentRowExpanded} + /> + + ); +}; diff --git a/packages/kbn-unified-data-table/src/components/data_table_footer.test.tsx b/packages/kbn-unified-data-table/src/components/data_table_footer.test.tsx new file mode 100644 index 0000000000000..d4aa0e9562f2b --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table_footer.test.tsx @@ -0,0 +1,140 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { mountWithIntl } from '@kbn/test-jest-helpers'; +import { findTestSubject } from '@elastic/eui/lib/test'; +import { UnifiedDataTableFooter } from './data_table_footer'; +import { servicesMock } from '../../__mocks__/services'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; + +describe('UnifiedDataTableFooter', function () { + it('should not render anything when not on the last page', async () => { + const component = mountWithIntl( + + + + ); + expect(component.isEmptyRender()).toBe(true); + }); + + 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, '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); + }); + + it('should render a message and the button for the last page', async () => { + const mockLoadMore = jest.fn(); + + const component = mountWithIntl( + + ); + expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe( + 'Search results are limited to 500 documents.Load more' + ); + + const button = findTestSubject(component, 'dscGridSampleSizeFetchMoreLink'); + expect(button.exists()).toBe(true); + + button.simulate('click'); + + expect(mockLoadMore).toHaveBeenCalledTimes(1); + }); + + it('should render a disabled button when loading more', async () => { + const mockLoadMore = jest.fn(); + + const component = mountWithIntl( + + ); + expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe( + 'Search results are limited to 500 documents.Load more' + ); + + const button = findTestSubject(component, 'dscGridSampleSizeFetchMoreLink'); + expect(button.exists()).toBe(true); + expect(button.prop('disabled')).toBe(true); + + button.simulate('click'); + + expect(mockLoadMore).not.toHaveBeenCalled(); + }); + + it('should render a message when max total limit is reached', async () => { + const component = mountWithIntl( + + ); + expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe( + 'Search results are limited to 10000 documents. Add more search terms to narrow your search.' + ); + }); +}); diff --git a/packages/kbn-unified-data-table/src/components/data_table_footer.tsx b/packages/kbn-unified-data-table/src/components/data_table_footer.tsx new file mode 100644 index 0000000000000..21819a023afed --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table_footer.tsx @@ -0,0 +1,164 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { FormattedMessage } from '@kbn/i18n-react'; +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 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 UnifiedDataTableFooterProps { + isLoadingMore?: boolean; + rowCount: number; + sampleSize: number; + pageIndex?: number; // starts from 0 + pageCount: number; + totalHits?: number; + onFetchMoreRecords?: () => void; + data: DataPublicPluginStart; + fieldFormats: FieldFormatsStart; +} + +export const UnifiedDataTableFooter: React.FC = (props) => { + const { + isLoadingMore, + rowCount, + sampleSize, + pageIndex, + pageCount, + totalHits = 0, + onFetchMoreRecords, + data, + } = props; + const timefilter = data.query.timefilter.timefilter; + const [refreshInterval, setRefreshInterval] = useState(timefilter.getRefreshInterval()); + + useEffect(() => { + const subscriber = timefilter.getRefreshIntervalUpdate$().subscribe(() => { + setRefreshInterval(timefilter.getRefreshInterval()); + }); + + return () => subscriber.unsubscribe(); + }, [timefilter, setRefreshInterval]); + + const isRefreshIntervalOn = Boolean( + refreshInterval && refreshInterval.pause === false && refreshInterval.value > 0 + ); + + const { euiTheme } = useEuiTheme(); + const isOnLastPage = pageIndex === pageCount - 1 && rowCount < totalHits; + + if (!isOnLastPage) { + return null; + } + + // allow to fetch more records for UnifiedDataTable + if (onFetchMoreRecords && typeof isLoadingMore === 'boolean') { + if (rowCount <= MAX_LOADED_GRID_ROWS - sampleSize) { + return ( + + + + + + + + ); + } + + return ; + } + + if (rowCount < totalHits) { + // show only a message for embeddable + return ; + } + + return null; +}; + +interface UnifiedDataTableFooterContainerProps extends UnifiedDataTableFooterProps { + hasButton: boolean; +} + +const UnifiedDataTableFooterContainer: React.FC = ({ + hasButton, + rowCount, + children, + fieldFormats, +}) => { + const { euiTheme } = useEuiTheme(); + + const formattedRowCount = fieldFormats + .getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER]) + .convert(rowCount); + + return ( +

    + + {hasButton ? ( + + ) : ( + + )} + + {children} +

    + ); +}; diff --git a/packages/kbn-unified-data-table/src/components/data_table_schema.ts b/packages/kbn-unified-data-table/src/components/data_table_schema.ts new file mode 100644 index 0000000000000..ad7a15feff1ca --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/data_table_schema.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 { KBN_FIELD_TYPES } from '@kbn/field-types'; +import { kibanaJSON } from '../constants'; + +export function getSchemaByKbnType(kbnType: string | undefined) { + // Default DataGrid schemas: boolean, numeric, datetime, json, currency, string + switch (kbnType) { + case KBN_FIELD_TYPES.IP: + case KBN_FIELD_TYPES.GEO_SHAPE: + case KBN_FIELD_TYPES.NUMBER: + return 'numeric'; + case KBN_FIELD_TYPES.BOOLEAN: + return 'boolean'; + case KBN_FIELD_TYPES.STRING: + return 'string'; + case KBN_FIELD_TYPES.DATE: + return 'datetime'; + default: + return kibanaJSON; + } +} + +export function getSchemaDetectors() { + return [ + { + type: kibanaJSON, + detector() { + return 0; // this schema is always explicitly defined + }, + sortTextAsc: '', + sortTextDesc: '', + icon: '', + color: '', + }, + ]; +} diff --git a/packages/kbn-unified-data-table/src/components/default_cell_actions.test.tsx b/packages/kbn-unified-data-table/src/components/default_cell_actions.test.tsx new file mode 100644 index 0000000000000..6ecaa850da6a1 --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/default_cell_actions.test.tsx @@ -0,0 +1,184 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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), + }; +}); + +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/packages/kbn-unified-data-table/src/components/default_cell_actions.tsx b/packages/kbn-unified-data-table/src/components/default_cell_actions.tsx new file mode 100644 index 0000000000000..6005d75ea6632 --- /dev/null +++ b/packages/kbn-unified-data-table/src/components/default_cell_actions.tsx @@ -0,0 +1,137 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useContext } from 'react'; +import { EuiDataGridColumnCellActionProps } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +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: DataTableContext, + rowIndex: EuiDataGridColumnCellActionProps['rowIndex'], + columnId: EuiDataGridColumnCellActionProps['columnId'], + mode: '+' | '-' +) { + const row = context.rows[rowIndex]; + const value = row.flattened[columnId]; + const field = context.dataView.fields.getByName(columnId); + + if (field && context.onFilter) { + context.onFilter(field, value, mode); + } +} + +export const FilterInBtn = ({ + Component, + rowIndex, + columnId, +}: EuiDataGridColumnCellActionProps) => { + const context = useContext(UnifiedDataTableContext); + const buttonTitle = i18n.translate('unifiedDataTable.grid.filterForAria', { + defaultMessage: 'Filter for this {value}', + values: { value: columnId }, + }); + + return ( + { + onFilterCell(context, rowIndex, columnId, '+'); + }} + iconType="plusInCircle" + aria-label={buttonTitle} + title={buttonTitle} + data-test-subj="filterForButton" + > + {i18n.translate('unifiedDataTable.grid.filterFor', { + defaultMessage: 'Filter for', + })} + + ); +}; + +export const FilterOutBtn = ({ + Component, + rowIndex, + columnId, +}: EuiDataGridColumnCellActionProps) => { + const context = useContext(UnifiedDataTableContext); + const buttonTitle = i18n.translate('unifiedDataTable.grid.filterOutAria', { + defaultMessage: 'Filter out this {value}', + values: { value: columnId }, + }); + + return ( + { + onFilterCell(context, rowIndex, columnId, '-'); + }} + iconType="minusInCircle" + aria-label={buttonTitle} + title={buttonTitle} + data-test-subj="filterOutButton" + > + {i18n.translate('unifiedDataTable.grid.filterOut', { + defaultMessage: 'Filter out', + })} + + ); +}; + +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 }, + }); + + return ( + { + copyValueToClipboard({ + rowIndex, + columnId, + valueToStringConverter, + toastNotifications, + }); + }} + iconType="copyClipboard" + aria-label={buttonTitle} + title={buttonTitle} + data-test-subj="copyClipboardButton" + > + {i18n.translate('unifiedDataTable.grid.copyCellValueButton', { + defaultMessage: 'Copy value', + })} + + ); +} + +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/packages/kbn-unified-data-table/src/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 new file mode 100644 index 0000000000000..e1ec1373f8657 --- /dev/null +++ b/packages/kbn-unified-data-table/src/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/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.tsx b/packages/kbn-unified-data-table/src/components/json_code_editor/json_code_editor.tsx new file mode 100644 index 0000000000000..d08e35eb6d4bf --- /dev/null +++ b/packages/kbn-unified-data-table/src/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/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/packages/kbn-unified-data-table/src/constants.ts b/packages/kbn-unified-data-table/src/constants.ts new file mode 100644 index 0000000000000..1fb391ddc7f70 --- /dev/null +++ b/packages/kbn-unified-data-table/src/constants.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 { EuiDataGridStyle } from '@elastic/eui'; + +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', + cellPadding: 's', + rowHover: 'none', +} as EuiDataGridStyle; + +export const toolbarVisibility = { + showColumnSelector: { + allowHide: false, + allowReorder: true, + }, +}; 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/packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.ts b/packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.ts new file mode 100644 index 0000000000000..088f7b0491c69 --- /dev/null +++ b/packages/kbn-unified-data-table/src/hooks/use_data_grid_columns.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { useEffect, useMemo, useState } from 'react'; +import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'; + +import { Capabilities } from '@kbn/core/public'; +import { isEqual } from 'lodash'; +import { getStateColumnActions } from '../components/actions/columns'; + +interface UseColumnsProps { + capabilities: Capabilities; + dataView: DataView; + dataViews: DataViewsContract; + useNewFieldsApi: boolean; + setAppState: (state: { columns: string[]; sort?: string[][] }) => void; + columns?: string[]; + sort?: string[][]; + defaultOrder?: string; +} + +export const useColumns = ({ + capabilities, + dataView, + dataViews, + setAppState, + useNewFieldsApi, + columns, + sort, + defaultOrder = 'desc', +}: UseColumnsProps) => { + const [usedColumns, setUsedColumns] = useState(getColumns(columns, useNewFieldsApi)); + useEffect(() => { + const nextColumns = getColumns(columns, useNewFieldsApi); + if (isEqual(usedColumns, nextColumns)) { + return; + } + setUsedColumns(nextColumns); + }, [columns, useNewFieldsApi, usedColumns]); + const { onAddColumn, onRemoveColumn, onSetColumns, onMoveColumn } = useMemo( + () => + getStateColumnActions({ + capabilities, + dataView, + dataViews, + setAppState, + useNewFieldsApi, + columns: usedColumns, + sort, + defaultOrder, + }), + [ + capabilities, + dataView, + dataViews, + defaultOrder, + setAppState, + sort, + useNewFieldsApi, + usedColumns, + ] + ); + + return { + columns: usedColumns, + onAddColumn, + onRemoveColumn, + onMoveColumn, + onSetColumns, + }; +}; + +function getColumns(columns: string[] | undefined, useNewFieldsApi: boolean) { + if (!columns) { + return []; + } + return useNewFieldsApi ? columns.filter((col) => col !== '_source') : columns; +} 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/packages/kbn-unified-data-table/src/table_context.tsx b/packages/kbn-unified-data-table/src/table_context.tsx new file mode 100644 index 0000000000000..2a1d4656d4a65 --- /dev/null +++ b/packages/kbn-unified-data-table/src/table_context.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { DataView } from '@kbn/data-views-plugin/public'; +import type { DataTableRecord } from '@kbn/discover-utils/types'; +import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; +import type { ValueToStringConverter } from './types'; + +export interface DataTableContext { + expanded?: DataTableRecord | undefined; + setExpanded?: (hit?: DataTableRecord) => void; + rows: DataTableRecord[]; + onFilter?: DocViewFilterFn; + dataView: DataView; + isDarkMode: boolean; + selectedDocs: string[]; + setSelectedDocs: (selected: string[]) => void; + valueToStringConverter: ValueToStringConverter; + componentsTourSteps?: Record; +} + +const defaultContext = {} as unknown as DataTableContext; + +export const UnifiedDataTableContext = React.createContext(defaultContext); diff --git a/packages/kbn-unified-data-table/src/types.ts b/packages/kbn-unified-data-table/src/types.ts new file mode 100644 index 0000000000000..79ca4e721e910 --- /dev/null +++ b/packages/kbn-unified-data-table/src/types.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. + */ + +/** + * 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 }; diff --git a/packages/kbn-unified-data-table/src/utils/columns.test.ts b/packages/kbn-unified-data-table/src/utils/columns.test.ts new file mode 100644 index 0000000000000..36a8b60a6bc68 --- /dev/null +++ b/packages/kbn-unified-data-table/src/utils/columns.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; +import { getDisplayedColumns } from './columns'; +import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; + +describe('getDisplayedColumns', () => { + test('returns default columns given a data view without timefield', async () => { + const result = getDisplayedColumns([], dataViewMock); + expect(result).toMatchInlineSnapshot(` + Array [ + "_source", + ] + `); + }); + test('returns default columns given a data view with timefield', async () => { + const result = getDisplayedColumns([], dataViewWithTimefieldMock); + expect(result).toMatchInlineSnapshot(` + Array [ + "_source", + ] + `); + }); + test('returns default columns when just timefield is in state', async () => { + const result = getDisplayedColumns(['timestamp'], dataViewWithTimefieldMock); + expect(result).toMatchInlineSnapshot(` + Array [ + "_source", + ] + `); + }); + test('returns columns given by argument, no fallback ', async () => { + const result = getDisplayedColumns(['test'], dataViewWithTimefieldMock); + expect(result).toMatchInlineSnapshot(` + Array [ + "test", + ] + `); + }); + test('returns the same instance of ["_source"] over multiple calls', async () => { + const result = getDisplayedColumns([], dataViewWithTimefieldMock); + const result2 = getDisplayedColumns([], dataViewWithTimefieldMock); + expect(result).toBe(result2); + }); +}); diff --git a/packages/kbn-unified-data-table/src/utils/columns.ts b/packages/kbn-unified-data-table/src/utils/columns.ts new file mode 100644 index 0000000000000..f2a72f0a8b650 --- /dev/null +++ b/packages/kbn-unified-data-table/src/utils/columns.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { 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 +// new columns, and thus performing worse than using the same array over multiple renders. +const SOURCE_ONLY = ['_source']; + +/** + * Function to provide fallback when + * 1) no columns are given + * 2) Just one column is given, which is the configured timefields + */ +export function getDisplayedColumns(stateColumns: string[] = [], dataView: DataView) { + return stateColumns && + stateColumns.length > 0 && + // check if all columns where removed except the configured timeField (this can't be removed) + !(stateColumns.length === 1 && stateColumns[0] === dataView.timeFieldName) + ? stateColumns + : SOURCE_ONLY; +} diff --git a/packages/kbn-unified-data-table/src/utils/convert_value_to_string.test.tsx b/packages/kbn-unified-data-table/src/utils/convert_value_to_string.test.tsx new file mode 100644 index 0000000000000..aa8ba719c5ba2 --- /dev/null +++ b/packages/kbn-unified-data-table/src/utils/convert_value_to_string.test.tsx @@ -0,0 +1,585 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { 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: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'keyword_key', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('abcd1'); + }); + + it('should convert a text value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'text_message', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('"Hi there! I am a sample string."'); + }); + + it('should convert a text value to text (not for CSV)', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'text_message', + rowIndex: 0, + options: { + compatibleWithCSV: false, + }, + }); + + expect(result.formattedString).toBe('Hi there! I am a sample string.'); + }); + + it('should convert a multiline text value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'text_message', + rowIndex: 1, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('"I\'m multiline\n*&%$#@"'); + expect(result.withFormula).toBe(false); + }); + + it('should convert a number value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'number_price', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('10.99'); + }); + + it('should convert a date value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'date', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('"2022-05-22T12:10:30.000Z"'); + }); + + it('should convert a date nanos value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'date_nanos', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('"2022-01-01T12:10:30.123456789Z"'); + }); + + it('should convert a date nanos value to text (not for CSV)', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'date_nanos', + rowIndex: 0, + options: { + compatibleWithCSV: false, + }, + }); + + expect(result.formattedString).toBe('2022-01-01T12:10:30.123456789Z'); + }); + + it('should convert a boolean value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'bool_enabled', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('false'); + }); + + it('should convert a binary value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'binary_blob', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('"U29tZSBiaW5hcnkgYmxvYg=="'); + }); + + it('should convert a binary value to text (not for CSV)', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'binary_blob', + rowIndex: 0, + options: { + compatibleWithCSV: false, + }, + }); + + expect(result.formattedString).toBe('U29tZSBiaW5hcnkgYmxvYg=='); + }); + + it('should convert an object value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'object_user.first', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('John'); + }); + + it('should convert a nested value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'nested_user', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe( + '{"last":["Smith"],"last.keyword":["Smith"],"first":["John"],"first.keyword":["John"]}, {"last":["White"],"last.keyword":["White"],"first":["Alice"],"first.keyword":["Alice"]}' + ); + }); + + it('should convert a flattened value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'flattened_labels', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('{"release":["v1.2.5","v1.3.0"],"priority":"urgent"}'); + }); + + it('should convert a range value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'range_time_frame', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe( + '{"gte":"2015-10-31 12:00:00","lte":"2015-11-01 00:00:00"}' + ); + }); + + it('should convert a rank features value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'rank_features', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('{"2star":100,"1star":10}'); + }); + + it('should convert a histogram value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'histogram', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('{"counts":[3,7,23,12,6],"values":[0.1,0.2,0.3,0.4,0.5]}'); + }); + + it('should convert a IP value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'ip_addr', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('"192.168.1.1"'); + }); + + it('should convert a IP value to text (not for CSV)', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'ip_addr', + rowIndex: 0, + options: { + compatibleWithCSV: false, + }, + }); + + expect(result.formattedString).toBe('192.168.1.1'); + }); + + it('should convert a version value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'version', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('"1.2.3"'); + }); + + it('should convert a version value to text (not for CSV)', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'version', + rowIndex: 0, + options: { + compatibleWithCSV: false, + }, + }); + + expect(result.formattedString).toBe('1.2.3'); + }); + + it('should convert a vector value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'vector', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('0.5, 10, 6'); + }); + + it('should convert a geo point value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'geo_point', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('{"coordinates":[-71.34,41.12],"type":"Point"}'); + }); + + it('should convert a geo point object value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'geo_point', + rowIndex: 1, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('{"coordinates":[-71.34,41.12],"type":"Point"}'); + }); + + it('should convert an array value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'array_tags', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('elasticsearch, wow'); + }); + + it('should convert a shape value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'geometry', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe( + '{"coordinates":[[[1000,-1001],[1001,-1001],[1001,-1000],[1000,-1000],[1000,-1001]]],"type":"Polygon"}' + ); + }); + + it('should convert a runtime value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'runtime_number', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('5.5'); + }); + + it('should convert a scripted value to text', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'scripted_string', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('"hi there"'); + }); + + it('should convert a scripted value to text (not for CSV)', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'scripted_string', + rowIndex: 0, + options: { + compatibleWithCSV: false, + }, + }); + + expect(result.formattedString).toBe('hi there'); + }); + + it('should return an empty string and not fail', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'unknown', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe(''); + }); + + it('should return an empty string when rowIndex is out of range', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'unknown', + rowIndex: -1, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe(''); + }); + + it('should return _source value', () => { + const result = convertValueToString({ + rows: dataTableContextMock.rows, + dataView: dataTableContextMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: '_source', + rowIndex: 0, + options: { + compatibleWithCSV: false, + }, + }); + + expect(result.formattedString).toBe( + '{\n' + + ' "bytes": 20,\n' + + ' "date": "2020-20-01T12:12:12.123",\n' + + ' "message": "test1",\n' + + ' "_index": "i",\n' + + ' "_score": 1\n' + + '}' + ); + }); + + it('should return a formatted _source value', () => { + const result = convertValueToString({ + rows: dataTableContextMock.rows, + dataView: dataTableContextMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: '_source', + rowIndex: 0, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe( + '{"bytes":20,"date":"2020-20-01T12:12:12.123","message":"test1","_index":"i","_score":1}' + ); + }); + + it('should escape formula', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'array_tags', + rowIndex: 1, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result.formattedString).toBe('"\'=1+2\'"" ;,=1+2"'); + expect(result.withFormula).toBe(true); + + const result2 = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'scripted_string', + rowIndex: 1, + options: { + compatibleWithCSV: true, + }, + }); + + expect(result2.formattedString).toBe('"\'=1+2"";=1+2"'); + expect(result2.withFormula).toBe(true); + }); + + it('should not escape formulas when not for CSV', () => { + const result = convertValueToString({ + rows: dataTableContextComplexMock.rows, + dataView: dataTableContextComplexMock.dataView, + fieldFormats: servicesMock.fieldFormats, + columnId: 'array_tags', + rowIndex: 1, + options: { + compatibleWithCSV: false, + }, + }); + + expect(result.formattedString).toBe('=1+2\'" ;,=1+2'); + expect(result.withFormula).toBe(true); + }); + + it('should return a formatted name', () => { + const result = convertNameToString('test'); + + expect(result.formattedString).toBe('test'); + expect(result.withFormula).toBe(false); + }); + + it('should return a formatted name when with a formula', () => { + const result = convertNameToString('=1+2";=1+2'); + + expect(result.formattedString).toBe('"\'=1+2"";=1+2"'); + expect(result.withFormula).toBe(true); + }); +}); 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/packages/kbn-unified-data-table/src/utils/row_heights.ts b/packages/kbn-unified-data-table/src/utils/row_heights.ts new file mode 100644 index 0000000000000..45f472286d030 --- /dev/null +++ b/packages/kbn-unified-data-table/src/utils/row_heights.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 type { Storage } from '@kbn/kibana-utils-plugin/public'; +import { isValidRowHeight } from './validate_row_height'; + +export interface DataGridOptionsRecord { + previousRowHeight: number; + previousConfigRowHeight: number; +} + +const getRowHeightKey = (consumer: string) => `${consumer}:dataGridRowHeight`; + +export const getStoredRowHeight = ( + storage: Storage, + consumer: string +): DataGridOptionsRecord | null => { + const entry = storage.get(getRowHeightKey(consumer)); + if ( + typeof entry === 'object' && + entry !== null && + isValidRowHeight(entry.previousRowHeight) && + isValidRowHeight(entry.previousConfigRowHeight) + ) { + return entry; + } + return null; +}; + +export const updateStoredRowHeight = ( + newRowHeight: number, + configRowHeight: number, + storage: Storage, + consumer: string +) => { + storage.set(getRowHeightKey(consumer), { + previousRowHeight: newRowHeight, + previousConfigRowHeight: configRowHeight, + }); +}; diff --git a/packages/kbn-unified-data-table/src/utils/rows_per_page.test.ts b/packages/kbn-unified-data-table/src/utils/rows_per_page.test.ts new file mode 100644 index 0000000000000..8da8ea099734b --- /dev/null +++ b/packages/kbn-unified-data-table/src/utils/rows_per_page.test.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 { getRowsPerPageOptions } from './rows_per_page'; + +const SORTED_OPTIONS = [10, 25, 50, 100, 250, 500]; + +describe('rows per page', () => { + describe('getRowsPerPageOptions', () => { + it('should return default options if not provided', () => { + expect(getRowsPerPageOptions()).toEqual(SORTED_OPTIONS); + }); + + it('should return default options if current value is one of them', () => { + expect(getRowsPerPageOptions(250)).toEqual(SORTED_OPTIONS); + }); + + it('should return extended options if current value is not one of them', () => { + expect(getRowsPerPageOptions(350)).toEqual([10, 25, 50, 100, 250, 350, 500]); + }); + }); +}); diff --git a/packages/kbn-unified-data-table/src/utils/rows_per_page.ts b/packages/kbn-unified-data-table/src/utils/rows_per_page.ts new file mode 100644 index 0000000000000..2eb547df1a36f --- /dev/null +++ b/packages/kbn-unified-data-table/src/utils/rows_per_page.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { sortBy, uniq } from 'lodash'; + +import { ROWS_PER_PAGE_OPTIONS } from '../constants'; + +export const getRowsPerPageOptions = (currentRowsPerPage?: number): number[] => { + return sortBy( + uniq( + typeof currentRowsPerPage === 'number' && currentRowsPerPage > 0 + ? [...ROWS_PER_PAGE_OPTIONS, currentRowsPerPage] + : ROWS_PER_PAGE_OPTIONS + ) + ); +}; 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/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx new file mode 100644 index 0000000000000..901208f8b3988 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { EuiTabbedContent } from '@elastic/eui'; +import { DocViewerTab } from './doc_viewer_tab'; +import type { DocView, DocViewRenderProps } from '../../types'; + +export interface DocViewerProps extends DocViewRenderProps { + docViews: DocView[]; +} + +/** + * Rendering tabs with different views of 1 Elasticsearch hit in Discover. + * The tabs are provided by the `docs_views` registry. + * A view can contain a React `component`, or any JS framework by using + * a `render` function. + */ +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. + // This condition takes care of unit tests with 0 tabs. + return null; + } + + return ( +
    + +
    + ); +} 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/packages/kbn-unified-doc-viewer/src/services/types.ts b/packages/kbn-unified-doc-viewer/src/services/types.ts new file mode 100644 index 0000000000000..0cce5ea3ff813 --- /dev/null +++ b/packages/kbn-unified-doc-viewer/src/services/types.ts @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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, DataViewField } from '@kbn/data-views-plugin/public'; +import type { AggregateQuery, Query } from '@kbn/es-query'; +import type { DataTableRecord, IgnoredReason } from '@kbn/discover-utils/types'; + +export interface FieldMapping { + filterable?: boolean; + scripted?: boolean; + rowCount?: number; + type: string; + name: string; + displayName?: string; +} + +export type DocViewFilterFn = ( + mapping: FieldMapping | string | undefined, + value: unknown, + mode: '+' | '-' +) => void; + +export interface DocViewRenderProps { + hit: DataTableRecord; + dataView: DataView; + columns?: string[]; + query?: Query | AggregateQuery; + textBasedHits?: DataTableRecord[]; + filter?: DocViewFilterFn; + onAddColumn?: (columnName: string) => void; + onRemoveColumn?: (columnName: string) => void; +} +export type DocViewerComponent = React.FC; +export type DocViewRenderFn = ( + domeNode: HTMLDivElement, + renderProps: DocViewRenderProps +) => () => void; + +export interface BaseDocViewInput { + order: number; + shouldShow?: (hit: DataTableRecord) => boolean; + title: string; +} + +export interface RenderDocViewInput extends BaseDocViewInput { + render: DocViewRenderFn; + component?: undefined; + directive?: undefined; +} + +interface ComponentDocViewInput extends BaseDocViewInput { + component: DocViewerComponent; + render?: undefined; + directive?: undefined; +} + +export type DocViewInput = ComponentDocViewInput | RenderDocViewInput; + +export type DocView = DocViewInput & { + shouldShow: NonNullable; +}; + +export type DocViewInputFn = () => DocViewInput; + +export interface FieldRecordLegacy { + action: { + isActive: boolean; + onFilter?: DocViewFilterFn; + onToggleColumn: (field: string) => void; + flattenedField: unknown; + }; + field: { + displayName: string; + field: string; + scripted: boolean; + fieldType?: string; + fieldMapping?: DataViewField; + }; + value: { + formattedValue: string; + ignored?: IgnoredReason; + }; +} 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/field_types.ts b/packages/kbn-unified-field-list/src/utils/field_types/field_types.ts deleted file mode 100644 index 0851d6dc1e412..0000000000000 --- a/packages/kbn-unified-field-list/src/utils/field_types/field_types.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { FieldTypeKnown } from '../../types'; - -/** - * Field types for which name and description are defined - * @public - */ -export enum KNOWN_FIELD_TYPES { - DOCUMENT = 'document', // "Records" on Lens page - BINARY = 'binary', - BOOLEAN = 'boolean', - CONFLICT = 'conflict', - COUNTER = 'counter', - DATE = 'date', - DATE_RANGE = 'date_range', - DENSE_VECTOR = 'dense_vector', - GAUGE = 'gauge', - GEO_POINT = 'geo_point', - GEO_SHAPE = 'geo_shape', - HISTOGRAM = 'histogram', - IP = 'ip', - IP_RANGE = 'ip_range', - FLATTENED = 'flattened', - KEYWORD = 'keyword', - MURMUR3 = 'murmur3', - NUMBER = 'number', - NESTED = 'nested', - RANK_FEATURE = 'rank_feature', - RANK_FEATURES = 'rank_features', - POINT = 'point', - SHAPE = 'shape', - STRING = 'string', - TEXT = 'text', - VERSION = 'version', -} - -export const KNOWN_FIELD_TYPE_LIST: string[] = Object.values(KNOWN_FIELD_TYPES); - -export const isKnownFieldType = (type?: string): type is FieldTypeKnown => { - return !!type && KNOWN_FIELD_TYPE_LIST.includes(type); -}; 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/get_field_type_name.ts b/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_name.ts deleted file mode 100644 index 23ae35a4c2ef3..0000000000000 --- a/packages/kbn-unified-field-list/src/utils/field_types/get_field_type_name.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { KBN_FIELD_TYPES } from '@kbn/field-types'; -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', - { - defaultMessage: 'Unknown field', - } -); - -/** - * Returns a user-friendly name of a field type - * @param type - * @public - */ -export function getFieldTypeName(type?: string) { - if (!type || type === KBN_FIELD_TYPES.UNKNOWN) { - return UNKNOWN_FIELD_TYPE_MESSAGE; - } - - if (type === 'source') { - // Note that this type is currently not provided, type for _source is undefined - return i18n.translate('unifiedFieldList.fieldNameIcons.sourceFieldAriaLabel', { - defaultMessage: 'Source field', - }); - } - - const knownType: KNOWN_FIELD_TYPES = type as KNOWN_FIELD_TYPES; - switch (knownType) { - case KNOWN_FIELD_TYPES.DOCUMENT: - return i18n.translate('unifiedFieldList.fieldNameIcons.recordAriaLabel', { - defaultMessage: 'Records', - }); - case KNOWN_FIELD_TYPES.BINARY: - return i18n.translate('unifiedFieldList.fieldNameIcons.binaryAriaLabel', { - defaultMessage: 'Binary', - }); - case KNOWN_FIELD_TYPES.BOOLEAN: - return i18n.translate('unifiedFieldList.fieldNameIcons.booleanAriaLabel', { - defaultMessage: 'Boolean', - }); - case KNOWN_FIELD_TYPES.CONFLICT: - return i18n.translate('unifiedFieldList.fieldNameIcons.conflictFieldAriaLabel', { - defaultMessage: 'Conflict', - }); - case KNOWN_FIELD_TYPES.COUNTER: - return i18n.translate('unifiedFieldList.fieldNameIcons.counterFieldAriaLabel', { - defaultMessage: 'Counter metric', - }); - case KNOWN_FIELD_TYPES.DATE: - return i18n.translate('unifiedFieldList.fieldNameIcons.dateFieldAriaLabel', { - defaultMessage: 'Date', - }); - case KNOWN_FIELD_TYPES.DATE_RANGE: - return i18n.translate('unifiedFieldList.fieldNameIcons.dateRangeFieldAriaLabel', { - defaultMessage: 'Date range', - }); - case KNOWN_FIELD_TYPES.DENSE_VECTOR: - return i18n.translate('unifiedFieldList.fieldNameIcons.denseVectorFieldAriaLabel', { - defaultMessage: 'Dense vector', - }); - case KNOWN_FIELD_TYPES.GAUGE: - return i18n.translate('unifiedFieldList.fieldNameIcons.gaugeFieldAriaLabel', { - defaultMessage: 'Gauge metric', - }); - case KNOWN_FIELD_TYPES.GEO_POINT: - return i18n.translate('unifiedFieldList.fieldNameIcons.geoPointFieldAriaLabel', { - defaultMessage: 'Geo point', - }); - case KNOWN_FIELD_TYPES.GEO_SHAPE: - return i18n.translate('unifiedFieldList.fieldNameIcons.geoShapeFieldAriaLabel', { - defaultMessage: 'Geo shape', - }); - case KNOWN_FIELD_TYPES.HISTOGRAM: - return i18n.translate('unifiedFieldList.fieldNameIcons.histogramFieldAriaLabel', { - defaultMessage: 'Histogram', - }); - case KNOWN_FIELD_TYPES.IP: - return i18n.translate('unifiedFieldList.fieldNameIcons.ipAddressFieldAriaLabel', { - defaultMessage: 'IP address', - }); - case KNOWN_FIELD_TYPES.IP_RANGE: - return i18n.translate('unifiedFieldList.fieldNameIcons.ipRangeFieldAriaLabel', { - defaultMessage: 'IP range', - }); - case KNOWN_FIELD_TYPES.FLATTENED: - return i18n.translate('unifiedFieldList.fieldNameIcons.flattenedFieldAriaLabel', { - defaultMessage: 'Flattened', - }); - case KNOWN_FIELD_TYPES.MURMUR3: - return i18n.translate('unifiedFieldList.fieldNameIcons.murmur3FieldAriaLabel', { - defaultMessage: 'Murmur3', - }); - case KNOWN_FIELD_TYPES.NUMBER: - return i18n.translate('unifiedFieldList.fieldNameIcons.numberFieldAriaLabel', { - defaultMessage: 'Number', - }); - case KNOWN_FIELD_TYPES.RANK_FEATURE: - return i18n.translate('unifiedFieldList.fieldNameIcons.rankFeatureFieldAriaLabel', { - defaultMessage: 'Rank feature', - }); - case KNOWN_FIELD_TYPES.RANK_FEATURES: - return i18n.translate('unifiedFieldList.fieldNameIcons.rankFeaturesFieldAriaLabel', { - defaultMessage: 'Rank features', - }); - case KNOWN_FIELD_TYPES.POINT: - return i18n.translate('unifiedFieldList.fieldNameIcons.pointFieldAriaLabel', { - defaultMessage: 'Point', - }); - case KNOWN_FIELD_TYPES.SHAPE: - return i18n.translate('unifiedFieldList.fieldNameIcons.shapeFieldAriaLabel', { - defaultMessage: 'Shape', - }); - case KNOWN_FIELD_TYPES.STRING: - return i18n.translate('unifiedFieldList.fieldNameIcons.stringFieldAriaLabel', { - defaultMessage: 'String', - }); - case KNOWN_FIELD_TYPES.TEXT: - return i18n.translate('unifiedFieldList.fieldNameIcons.textFieldAriaLabel', { - defaultMessage: 'Text', - }); - case KNOWN_FIELD_TYPES.KEYWORD: - return i18n.translate('unifiedFieldList.fieldNameIcons.keywordFieldAriaLabel', { - defaultMessage: 'Keyword', - }); - case KNOWN_FIELD_TYPES.NESTED: - return i18n.translate('unifiedFieldList.fieldNameIcons.nestedFieldAriaLabel', { - defaultMessage: 'Nested', - }); - case KNOWN_FIELD_TYPES.VERSION: - return i18n.translate('unifiedFieldList.fieldNameIcons.versionFieldAriaLabel', { - defaultMessage: 'Version', - }); - default: - // If you see a typescript error here, that's a sign that there are missing switch cases ^^ - const _exhaustiveCheck: never = knownType; - return knownType || _exhaustiveCheck; - } -} 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/http/router.test.ts b/src/core/server/integration_tests/http/router.test.ts index 743624f2f46b3..de5e10d1ee599 100644 --- a/src/core/server/integration_tests/http/router.test.ts +++ b/src/core/server/integration_tests/http/router.test.ts @@ -576,11 +576,19 @@ describe('Handler', () => { 'An internal server error occurred. Check Kibana server logs for details.' ); expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` + Array [ Array [ - Array [ - [Error: unexpected error], - ], - ] + "500 Server Error - /", + Object { + "error": [Error: unexpected error], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, + ], + ] `); }); @@ -617,7 +625,15 @@ describe('Handler', () => { expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` Array [ Array [ - [Error: Unauthorized], + "500 Server Error - /", + Object { + "error": [Error: Unauthorized], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, ], ] `); @@ -639,7 +655,15 @@ describe('Handler', () => { expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` Array [ Array [ - [Error: Unexpected result from Route Handler. Expected KibanaResponse, but given: string.], + "500 Server Error - /", + Object { + "error": [Error: Unexpected result from Route Handler. Expected KibanaResponse, but given: string.], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, ], ] `); @@ -672,6 +696,22 @@ describe('Handler', () => { message: '[request query.page]: expected value of type [number] but got [string]', statusCode: 400, }); + + expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` + Array [ + Array [ + "400 Bad Request - /", + Object { + "error": [Error: [request query.page]: expected value of type [number] but got [string]], + "http": Object { + "response": Object { + "status_code": 400, + }, + }, + }, + ], + ] + `); }); it('accept to receive an array payload', async () => { @@ -1145,7 +1185,15 @@ describe('Response factory', () => { expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` Array [ Array [ - [Error: expected 'location' header to be set], + "500 Server Error - /", + Object { + "error": [Error: expected 'location' header to be set], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, ], ] `); @@ -1551,7 +1599,15 @@ describe('Response factory', () => { expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` Array [ Array [ - [Error: Unexpected Http status code. Expected from 400 to 599, but given: 200], + "500 Server Error - /", + Object { + "error": [Error: Unexpected Http status code. Expected from 400 to 599, but given: 200], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, ], ] `); @@ -1620,7 +1676,15 @@ describe('Response factory', () => { expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` Array [ Array [ - [Error: expected 'location' header to be set], + "500 Server Error - /", + Object { + "error": [Error: expected 'location' header to be set], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, ], ] `); @@ -1760,7 +1824,15 @@ describe('Response factory', () => { expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` Array [ Array [ - [Error: expected error message to be provided], + "500 Server Error - /", + Object { + "error": [Error: expected error message to be provided], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, ], ] `); @@ -1786,7 +1858,15 @@ describe('Response factory', () => { expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` Array [ Array [ - [Error: expected error message to be provided], + "500 Server Error - /", + Object { + "error": [Error: expected error message to be provided], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, ], ] `); @@ -1811,7 +1891,15 @@ describe('Response factory', () => { expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` Array [ Array [ - [Error: options.statusCode is expected to be set. given options: undefined], + "500 Server Error - /", + Object { + "error": [Error: options.statusCode is expected to be set. given options: undefined], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, ], ] `); @@ -1836,7 +1924,15 @@ describe('Response factory', () => { expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` Array [ Array [ - [Error: Unexpected Http status code. Expected from 100 to 599, but given: 20.], + "500 Server Error - /", + Object { + "error": [Error: Unexpected Http status code. Expected from 100 to 599, but given: 20.], + "http": Object { + "response": Object { + "status_code": 500, + }, + }, + }, ], ] `); 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 221002a3c33bc..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,13 +120,13 @@ 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", "osquery-saved-query": "44f1161e165defe3f9b6ad643c68c542a765fcdb", - "query": "8db5d48c62d75681d80d82a42b5642f60d068202", - "risk-engine-configuration": "1b8b175e29ea5311408125c92c6247f502b2d79d", + "query": "21cbbaa09abb679078145ce90087b1e88b7eae95", + "risk-engine-configuration": "b105d4a3c6adce40708d729d12e5ef3c8fbd9508", "rules-settings": "892a2918ebaeba809a612b8d97cec0b07c800b5f", "sample-data-telemetry": "37441b12f5b0159c2d6d5138a494c9f440e950b5", "search": "8d5184dd5b986d57250b6ffd9ae48a1925e4c7a3", 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/jest.integration.config.js b/src/core/server/integration_tests/saved_objects/serverless/migrations/jest.integration.config.js new file mode 100644 index 0000000000000..7341478b60a69 --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/serverless/migrations/jest.integration.config.js @@ -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. + */ + +module.exports = { + // TODO replace the line below with + // preset: '@kbn/test/jest_integration_node + // to do so, we must fix all integration tests first + // see https://github.com/elastic/kibana/pull/130255/ + preset: '@kbn/test/jest_integration', + rootDir: '../../../../../../..', + roots: ['/src/core/server/integration_tests/saved_objects/serverless/migrations'], + // must override to match all test given there is no `integration_tests` subfolder + testMatch: ['**/*.test.{js,mjs,ts,tsx}'], +}; 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 new file mode 100644 index 0000000000000..1d884706fc8ba --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/serverless/migrations/smoke.test.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { + request, + TestServerlessESUtils, + TestServerlessKibanaUtils, + createTestServerlessInstances, +} from '@kbn/core-test-helpers-kbn-server'; + +describe('smoke', () => { + let serverlessES: TestServerlessESUtils; + let serverlessKibana: TestServerlessKibanaUtils; + let root: TestServerlessKibanaUtils['root']; + beforeEach(async () => { + const { startES, startKibana } = createTestServerlessInstances({ + adjustTimeout: jest.setTimeout, + }); + serverlessES = await startES(); + serverlessKibana = await startKibana(); + root = serverlessKibana.root; + }); + afterEach(async () => { + await serverlessES?.stop(); + await serverlessKibana?.stop(); + }); + test('it can start Kibana and ES serverless', async () => { + const { body } = await request.get(root, '/api/status').expect(200); + expect(body).toMatchObject({ status: { overall: { level: 'available' } } }); + }); +}); 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/license_checker/config.ts b/src/dev/license_checker/config.ts index f9b3a6d02e9eb..c239333d00590 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -85,7 +85,7 @@ export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@8.4.0': ['Elastic License 2.0'], - '@elastic/eui@87.1.0': ['SSPL-1.0 OR Elastic License 2.0'], + '@elastic/eui@87.2.0': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry 'buffers@0.1.1': ['MIT'], // license in importing module https://www.npmjs.com/package/binary }; 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/charts/common/static/components/collections.ts b/src/plugins/charts/common/static/components/collections.ts index 1f138ab9f7b0e..acb11c647fead 100644 --- a/src/plugins/charts/common/static/components/collections.ts +++ b/src/plugins/charts/common/static/components/collections.ts @@ -20,6 +20,7 @@ export const LabelRotation = Object.freeze({ Horizontal: 0, Vertical: 90, Angled: 75, + VerticalRotation: 270, }); export type LabelRotation = $Values; diff --git a/src/plugins/console/public/lib/autocomplete/autocomplete.ts b/src/plugins/console/public/lib/autocomplete/autocomplete.ts index 71cca78926459..04634e635ac12 100644 --- a/src/plugins/console/public/lib/autocomplete/autocomplete.ts +++ b/src/plugins/console/public/lib/autocomplete/autocomplete.ts @@ -42,6 +42,19 @@ function isUrlParamsToken(token: { type: string } | null) { } } +const tracer = (...args: any[]) => { + // @ts-expect-error ts upgrade v4.7.4 + if (window.autocomplete_trace) { + // eslint-disable-next-line no-console + console.log.call( + console, + ..._.map(args, (arg) => { + return typeof arg === 'object' ? JSON.stringify(arg) : arg; + }) + ); + } +}; + /** * Get the method and token paths for a specific position in the current editor buffer. * @@ -131,7 +144,7 @@ export function getCurrentMethodAndTokenPaths( } } if (!t) { - // oops we run out.. we don't know what's up return null; + tracer(`paren.rparen: oops we run out.. we don't know what's up return null`); return {}; } continue; @@ -145,7 +158,7 @@ export function getCurrentMethodAndTokenPaths( } } if (!t) { - // oops we run out.. we don't know what's up return null; + tracer(`paren.rparen: oops we run out.. we don't know what's up return null`); return {}; } continue; @@ -183,7 +196,11 @@ export function getCurrentMethodAndTokenPaths( } if (walkedSomeBody && (!bodyTokenPath || bodyTokenPath.length === 0) && !forceEndOfUrl) { - // we had some content and still no path -> the cursor is position after a closed body -> no auto complete + tracer( + 'we had some content and still no path', + '-> the cursor is position after a closed body', + '-> no auto complete' + ); return {}; } @@ -594,7 +611,8 @@ export default function ({ context.autoCompleteType === 'body' && !!context.asyncResultsState?.isLoading; if (!context.autoCompleteSet && !isMappingsFetchingInProgress) { - return null; // nothing to do.. + tracer('nothing to do..', context); + return null; } addReplacementInfoToContext(context, pos); @@ -1056,12 +1074,10 @@ export default function ({ pos: Position ) { let currentToken = editor.getTokenAt(pos)!; + tracer('has started evaluating current token', currentToken); if (!currentToken) { - if (pos.lineNumber === 1) { - lastEvaluatedToken = null; - return; - } + lastEvaluatedToken = null; currentToken = { position: { column: 0, lineNumber: 0 }, value: '', type: '' }; // empty row } @@ -1077,22 +1093,54 @@ export default function ({ nextToken.position.lineNumber = pos.lineNumber; lastEvaluatedToken = nextToken; } + tracer('not starting autocomplete due to empty current token'); return; } if (!lastEvaluatedToken) { lastEvaluatedToken = currentToken; + tracer('not starting autocomplete due to invalid last evaluated token'); return; // wait for the next typing. } - // if the column or the line number have not changed for the last token and - // user did not provided a new value, then we should not show autocomplete - // this guards against triggering autocomplete when clicking around the editor if ( - (lastEvaluatedToken.position.column !== currentToken.position.column || - lastEvaluatedToken.position.lineNumber !== currentToken.position.lineNumber) && + lastEvaluatedToken.position.column + 1 === currentToken.position.column && + lastEvaluatedToken.position.lineNumber === currentToken.position.lineNumber && + lastEvaluatedToken.type === 'url.slash' && + currentToken.type === 'url.part' && + currentToken.value.length === 1 + ) { + // do not suppress autocomplete for a single character immediately following a slash in URL + } else if ( + lastEvaluatedToken.position.column < currentToken.position.column && + lastEvaluatedToken.position.lineNumber === currentToken.position.lineNumber && + lastEvaluatedToken.type === 'method' && + currentToken.type === 'url.part' && + currentToken.value.length === 1 + ) { + // do not suppress autocomplete for a single character following method in URL + } else if ( + lastEvaluatedToken.position.column < currentToken.position.column && + lastEvaluatedToken.position.lineNumber === currentToken.position.lineNumber && + !lastEvaluatedToken.type && + currentToken.type === 'method' && + currentToken.value.length === 1 + ) { + // do not suppress autocompletion for the first character of method + } else if ( + // if the column or the line number have changed for the last token or + // user did not provided a new value, then we should not show autocomplete + // this guards against triggering autocomplete when clicking around the editor + lastEvaluatedToken.position.column !== currentToken.position.column || + lastEvaluatedToken.position.lineNumber !== currentToken.position.lineNumber || lastEvaluatedToken.value === currentToken.value ) { + tracer( + 'not starting autocomplete since the change looks like a click', + lastEvaluatedToken, + '->', + currentToken + ); // not on the same place or nothing changed, cache and wait for the next time lastEvaluatedToken = currentToken; return; @@ -1108,9 +1156,11 @@ export default function ({ case 'comment.punctuation': case 'comment.block': case 'UNKNOWN': + tracer('not starting autocomplete for current token type', currentToken.type); return; } + tracer('starting autocomplete', lastEvaluatedToken, '->', currentToken); lastEvaluatedToken = currentToken; editor.execCommand('startAutocomplete'); }, @@ -1118,7 +1168,9 @@ export default function ({ function editorChangeListener() { const position = editor.getCurrentPosition(); + tracer('editor changed', position); if (position && !editor.isCompleterActive()) { + tracer('will start evaluating current token'); evaluateCurrentTokenAfterAChange(position); } } @@ -1208,11 +1260,13 @@ export default function ({ const context = getAutoCompleteContext(editor, position); if (!context) { + tracer('zero suggestions due to invalid autocomplete context'); callback(null, []); } else { if (!context.asyncResultsState?.isLoading) { const terms = getTerms(context, context.autoCompleteSet!); const suggestions = getSuggestions(terms); + tracer(suggestions?.length ?? 0, 'suggestions'); callback(null, suggestions); } @@ -1225,6 +1279,7 @@ export default function ({ context.asyncResultsState.results.then((r) => { const asyncSuggestions = getSuggestions(getTerms(context, r)); + tracer(asyncSuggestions?.length ?? 0, 'async suggestions'); callback(null, asyncSuggestions); annotationControls.removeAnnotation(); }); diff --git a/src/plugins/dashboard/common/content_management/v1/types.ts b/src/plugins/dashboard/common/content_management/v1/types.ts index 9d89d724ed00f..05d216e8a785e 100644 --- a/src/plugins/dashboard/common/content_management/v1/types.ts +++ b/src/plugins/dashboard/common/content_management/v1/types.ts @@ -49,8 +49,14 @@ export interface SavedDashboardPanel { panelRefName?: string; gridData: GridData; panelIndex: string; - version: string; title?: string; + + /** + * This version key was used to store Kibana version information from versions 7.3.0 -> 8.11.0. + * As of version 8.11.0, the versioning information is now per-embeddable-type and is stored on the + * embeddable's input. (embeddableConfig in this type). + */ + version?: string; } /* eslint-disable-next-line @typescript-eslint/consistent-type-definitions */ diff --git a/src/plugins/dashboard/common/dashboard_container/types.ts b/src/plugins/dashboard/common/dashboard_container/types.ts index 139277be9315f..b4c6a874f0651 100644 --- a/src/plugins/dashboard/common/dashboard_container/types.ts +++ b/src/plugins/dashboard/common/dashboard_container/types.ts @@ -29,6 +29,13 @@ export interface DashboardPanelState< > extends PanelState { readonly gridData: GridData; panelRefName?: string; + + /** + * This version key was used to store Kibana version information from versions 7.3.0 -> 8.11.0. + * As of version 8.11.0, the versioning information is now per-embeddable-type and is stored on the + * embeddable's input. This key is needed for BWC, but its value will be removed on Dashboard save. + */ + version?: string; } export type DashboardContainerByReferenceInput = SavedObjectEmbeddableInput; diff --git a/src/plugins/dashboard/common/dashboard_saved_object/persistable_state/dashboard_saved_object_references.test.ts b/src/plugins/dashboard/common/dashboard_saved_object/persistable_state/dashboard_saved_object_references.test.ts index c43654187634d..e93def3fa47a7 100644 --- a/src/plugins/dashboard/common/dashboard_saved_object/persistable_state/dashboard_saved_object_references.test.ts +++ b/src/plugins/dashboard/common/dashboard_saved_object/persistable_state/dashboard_saved_object_references.test.ts @@ -51,190 +51,6 @@ const commonAttributes: DashboardAttributes = { title: '', }; -describe('legacy extract references', () => { - test('extracts references from panelsJSON', () => { - const doc = { - id: '1', - attributes: { - ...commonAttributes, - foo: true, - panelsJSON: JSON.stringify([ - { - type: 'visualization', - id: '1', - title: 'Title 1', - version: '7.0.0', - }, - { - type: 'visualization', - id: '2', - title: 'Title 2', - version: '7.0.0', - }, - ]), - }, - references: [], - }; - const updatedDoc = extractReferences(doc, deps); - - expect(updatedDoc).toMatchInlineSnapshot(` - Object { - "attributes": Object { - "description": "", - "foo": true, - "kibanaSavedObjectMeta": Object { - "searchSourceJSON": "", - }, - "panelsJSON": "[{\\"title\\":\\"Title 1\\",\\"version\\":\\"7.0.0\\",\\"panelRefName\\":\\"panel_0\\"},{\\"title\\":\\"Title 2\\",\\"version\\":\\"7.0.0\\",\\"panelRefName\\":\\"panel_1\\"}]", - "timeRestore": false, - "title": "", - "version": 1, - }, - "references": Array [ - Object { - "id": "1", - "name": "panel_0", - "type": "visualization", - }, - Object { - "id": "2", - "name": "panel_1", - "type": "visualization", - }, - ], - } - `); - }); - - test('fails when "type" attribute is missing from a panel', () => { - const doc = { - id: '1', - attributes: { - ...commonAttributes, - foo: true, - panelsJSON: JSON.stringify([ - { - id: '1', - title: 'Title 1', - version: '7.0.0', - }, - ]), - }, - references: [], - }; - expect(() => extractReferences(doc, deps)).toThrowErrorMatchingInlineSnapshot( - `"\\"type\\" attribute is missing from panel \\"0\\""` - ); - }); - - test('passes when "id" attribute is missing from a panel', () => { - const doc = { - id: '1', - attributes: { - ...commonAttributes, - foo: true, - panelsJSON: JSON.stringify([ - { - type: 'visualization', - title: 'Title 1', - version: '7.9.1', - }, - ]), - }, - references: [], - }; - expect(extractReferences(doc, deps)).toMatchInlineSnapshot(` - Object { - "attributes": Object { - "description": "", - "foo": true, - "kibanaSavedObjectMeta": Object { - "searchSourceJSON": "", - }, - "panelsJSON": "[{\\"version\\":\\"7.9.1\\",\\"type\\":\\"visualization\\",\\"embeddableConfig\\":{},\\"title\\":\\"Title 1\\"}]", - "timeRestore": false, - "title": "", - "version": 1, - }, - "references": Array [], - } - `); - }); - - // https://github.com/elastic/kibana/issues/93772 - test('passes when received older RAW SO with older panels', () => { - const doc = { - id: '1', - attributes: { - hits: 0, - timeFrom: 'now-16h/h', - timeTo: 'now', - refreshInterval: { - display: '1 minute', - section: 2, - value: 60000, - pause: false, - }, - description: '', - uiStateJSON: '{"P-1":{"vis":{"legendOpen":false}}}', - title: 'Errors/Fatals/Warnings dashboard', - timeRestore: true, - version: 1, - panelsJSON: - '[{"col":1,"id":"544891f0-2cf2-11e8-9735-93e95b055f48","panelIndex":1,"row":1,"size_x":12,"size_y":8,"type":"visualization"}]', - optionsJSON: '{"darkTheme":true}', - kibanaSavedObjectMeta: { - searchSourceJSON: - '{"highlightAll":true,"filter":[{"query":{"query_string":{"analyze_wildcard":true,"query":"*"}}}]}', - }, - }, - references: [], - }; - const updatedDoc = extractReferences(doc, deps); - - expect(updatedDoc).toMatchInlineSnapshot(` - Object { - "attributes": Object { - "description": "", - "hits": 0, - "kibanaSavedObjectMeta": Object { - "searchSourceJSON": "{\\"highlightAll\\":true,\\"filter\\":[{\\"query\\":{\\"query_string\\":{\\"analyze_wildcard\\":true,\\"query\\":\\"*\\"}}}]}", - }, - "optionsJSON": "{\\"darkTheme\\":true}", - "panelsJSON": "[{\\"col\\":1,\\"panelIndex\\":1,\\"row\\":1,\\"size_x\\":12,\\"size_y\\":8,\\"panelRefName\\":\\"panel_0\\"}]", - "refreshInterval": Object { - "display": "1 minute", - "pause": false, - "section": 2, - "value": 60000, - }, - "timeFrom": "now-16h/h", - "timeRestore": true, - "timeTo": "now", - "title": "Errors/Fatals/Warnings dashboard", - "uiStateJSON": "{\\"P-1\\":{\\"vis\\":{\\"legendOpen\\":false}}}", - "version": 1, - }, - "references": Array [ - Object { - "id": "544891f0-2cf2-11e8-9735-93e95b055f48", - "name": "panel_0", - "type": "visualization", - }, - ], - } - `); - - const panel = JSON.parse(updatedDoc.attributes.panelsJSON as string)[0]; - - // unknown older panel keys are left untouched - expect(panel).toHaveProperty('col'); - expect(panel).toHaveProperty('row'); - expect(panel).toHaveProperty('size_x'); - expect(panel).toHaveProperty('size_y'); - }); -}); - describe('extractReferences', () => { test('extracts references from panelsJSON', () => { const doc = { diff --git a/src/plugins/dashboard/common/dashboard_saved_object/persistable_state/dashboard_saved_object_references.ts b/src/plugins/dashboard/common/dashboard_saved_object/persistable_state/dashboard_saved_object_references.ts index f8a1c089d2fc3..b25c07a4342c9 100644 --- a/src/plugins/dashboard/common/dashboard_saved_object/persistable_state/dashboard_saved_object_references.ts +++ b/src/plugins/dashboard/common/dashboard_saved_object/persistable_state/dashboard_saved_object_references.ts @@ -5,7 +5,6 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import semverGt from 'semver/functions/gt'; import { Reference } from '@kbn/content-management-utils'; import { EmbeddablePersistableStateService } from '@kbn/embeddable-plugin/common/types'; @@ -22,10 +21,6 @@ export interface InjectExtractDeps { embeddablePersistableStateService: EmbeddablePersistableStateService; } -const isPre730Panel = (panel: Record): boolean => { - return 'version' in panel && panel.version ? semverGt('7.3.0', panel.version) : true; -}; - function parseDashboardAttributesWithType( attributes: DashboardAttributes ): ParsedDashboardAttributesWithType { @@ -82,10 +77,6 @@ export function extractReferences( const panels = parsedAttributes.panels; - if ((Object.values(panels) as unknown as Array>).some(isPre730Panel)) { - return pre730ExtractReferences({ attributes, references }); - } - const panelMissingType = Object.values(panels).find((panel) => panel.type === undefined); if (panelMissingType) { throw new Error( @@ -117,41 +108,3 @@ export function extractReferences( attributes: newAttributes, }; } - -function pre730ExtractReferences({ - attributes, - references = [], -}: DashboardAttributesAndReferences): DashboardAttributesAndReferences { - if (typeof attributes.panelsJSON !== 'string') { - return { attributes, references }; - } - const panelReferences: Reference[] = []; - const panels: Array> = JSON.parse(String(attributes.panelsJSON)); - - panels.forEach((panel, i) => { - if (!panel.type) { - throw new Error(`"type" attribute is missing from panel "${i}"`); - } - if (!panel.id) { - // Embeddables are not required to be backed off a saved object. - return; - } - - panel.panelRefName = `panel_${i}`; - panelReferences.push({ - name: `panel_${i}`, - type: panel.type, - id: panel.id, - }); - delete panel.type; - delete panel.id; - }); - - return { - references: [...references, ...panelReferences], - attributes: { - ...attributes, - panelsJSON: JSON.stringify(panels), - }, - }; -} diff --git a/src/plugins/dashboard/common/lib/dashboard_panel_converters.test.ts b/src/plugins/dashboard/common/lib/dashboard_panel_converters.test.ts index f9da81d5d998b..b1865571e42b9 100644 --- a/src/plugins/dashboard/common/lib/dashboard_panel_converters.test.ts +++ b/src/plugins/dashboard/common/lib/dashboard_panel_converters.test.ts @@ -89,7 +89,7 @@ test('convertPanelStateToSavedDashboardPanel', () => { type: 'search', }; - expect(convertPanelStateToSavedDashboardPanel(dashboardPanel, '6.3.0')).toEqual({ + expect(convertPanelStateToSavedDashboardPanel(dashboardPanel)).toEqual({ type: 'search', embeddableConfig: { something: 'hi!', @@ -103,7 +103,6 @@ test('convertPanelStateToSavedDashboardPanel', () => { w: 15, i: '123', }, - version: '6.3.0', }); }); @@ -123,7 +122,7 @@ test('convertPanelStateToSavedDashboardPanel will not add an undefined id when n type: 'search', }; - const converted = convertPanelStateToSavedDashboardPanel(dashboardPanel, '8.0.0'); + const converted = convertPanelStateToSavedDashboardPanel(dashboardPanel); expect(converted.hasOwnProperty('id')).toBe(false); }); @@ -143,7 +142,49 @@ test('convertPanelStateToSavedDashboardPanel will not leave title as part of emb type: 'search', }; - const converted = convertPanelStateToSavedDashboardPanel(dashboardPanel, '8.0.0'); + const converted = convertPanelStateToSavedDashboardPanel(dashboardPanel); expect(converted.embeddableConfig.hasOwnProperty('title')).toBe(false); expect(converted.title).toBe('title'); }); + +test('convertPanelStateToSavedDashboardPanel retains legacy version info when not passed removeLegacyVersion', () => { + const dashboardPanel: DashboardPanelState = { + gridData: { + x: 0, + y: 0, + h: 15, + w: 15, + i: '123', + }, + explicitInput: { + id: '123', + title: 'title', + } as EmbeddableInput, + type: 'search', + version: '8.10.0', + }; + + const converted = convertPanelStateToSavedDashboardPanel(dashboardPanel); + expect(converted.version).toBe('8.10.0'); +}); + +test('convertPanelStateToSavedDashboardPanel removes legacy version info when passed removeLegacyVersion', () => { + const dashboardPanel: DashboardPanelState = { + gridData: { + x: 0, + y: 0, + h: 15, + w: 15, + i: '123', + }, + explicitInput: { + id: '123', + title: 'title', + } as EmbeddableInput, + type: 'search', + version: '8.10.0', + }; + + const converted = convertPanelStateToSavedDashboardPanel(dashboardPanel, true); + expect(converted.version).not.toBeDefined(); +}); diff --git a/src/plugins/dashboard/common/lib/dashboard_panel_converters.ts b/src/plugins/dashboard/common/lib/dashboard_panel_converters.ts index 117d949c6c097..052dd6532fc44 100644 --- a/src/plugins/dashboard/common/lib/dashboard_panel_converters.ts +++ b/src/plugins/dashboard/common/lib/dashboard_panel_converters.ts @@ -17,7 +17,6 @@ export function convertSavedDashboardPanelToPanelState< >(savedDashboardPanel: SavedDashboardPanel): DashboardPanelState { return { type: savedDashboardPanel.type, - version: savedDashboardPanel.version, gridData: savedDashboardPanel.gridData, panelRefName: savedDashboardPanel.panelRefName, explicitInput: { @@ -26,16 +25,29 @@ export function convertSavedDashboardPanelToPanelState< ...(savedDashboardPanel.title !== undefined && { title: savedDashboardPanel.title }), ...savedDashboardPanel.embeddableConfig, } as TEmbeddableInput, + + /** + * Version information used to be stored in the panel until 8.11 when it was moved + * to live inside the explicit Embeddable Input. If version information is given here, we'd like to keep it. + * It will be removed on Dashboard save + */ + version: savedDashboardPanel.version, }; } export function convertPanelStateToSavedDashboardPanel( panelState: DashboardPanelState, - version?: string + removeLegacyVersion?: boolean ): SavedDashboardPanel { const savedObjectId = (panelState.explicitInput as SavedObjectEmbeddableInput).savedObjectId; return { - version: version ?? (panelState.version as string), // temporary cast. Version will be mandatory at a later date. + /** + * Version information used to be stored in the panel until 8.11 when it was moved to live inside the + * explicit Embeddable Input. If removeLegacyVersion is not passed, we'd like to keep this information for + * the time being. + */ + ...(!removeLegacyVersion ? { version: panelState.version } : {}), + type: panelState.type, gridData: panelState.gridData, panelIndex: panelState.explicitInput.id, @@ -56,9 +68,9 @@ export const convertSavedPanelsToPanelMap = (panels?: SavedDashboardPanel[]): Da export const convertPanelMapToSavedPanels = ( panels: DashboardPanelMap, - versionOverride?: string + removeLegacyVersion?: boolean ) => { return Object.values(panels).map((panel) => - convertPanelStateToSavedDashboardPanel(panel, versionOverride) + convertPanelStateToSavedDashboardPanel(panel, removeLegacyVersion) ); }; 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/_dashboard_app_strings.ts b/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts index ec2bb389755a7..aa25647610e2b 100644 --- a/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts +++ b/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts @@ -51,6 +51,15 @@ export const unsavedChangesBadgeStrings = { defaultMessage: ' You have unsaved changes in this dashboard. To remove this label, save the dashboard.', }), + getHasRunMigrationsText: () => + i18n.translate('dashboard.hasRunMigrationsBadge', { + defaultMessage: 'Save recommended', + }), + getHasRunMigrationsToolTipContent: () => + i18n.translate('dashboard.hasRunMigrationsBadgeToolTipContent', { + defaultMessage: + 'One or more panels on this dashboard have been updated to a new version. Save the dashboard so it loads faster next time.', + }), }; export const leaveConfirmStrings = { 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_app/top_nav/dashboard_top_nav.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx index d6e61f9e1c88b..8fbd259be6eec 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx @@ -16,8 +16,9 @@ import { } from '@kbn/presentation-util-plugin/public'; import { ViewMode } from '@kbn/embeddable-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; - +import { TopNavMenuProps } from '@kbn/navigation-plugin/public'; import { EuiHorizontalRule, EuiIcon, EuiToolTipProps } from '@elastic/eui'; + import { getDashboardTitle, leaveConfirmStrings, @@ -74,6 +75,9 @@ export function DashboardTopNav({ embedSettings, redirectTo }: DashboardTopNavPr const dashboard = useDashboardAPI(); const PresentationUtilContextProvider = getPresentationUtilContextProvider(); + const hasRunMigrations = dashboard.select( + (state) => state.componentState.hasRunClientsideMigrations + ); const hasUnsavedChanges = dashboard.select((state) => state.componentState.hasUnsavedChanges); const fullScreenMode = dashboard.select((state) => state.componentState.fullScreenMode); const savedQueryId = dashboard.select((state) => state.componentState.savedQueryId); @@ -232,6 +236,37 @@ export function DashboardTopNav({ embedSettings, redirectTo }: DashboardTopNavPr dashboard.clearOverlays(); }); + const badges = useMemo(() => { + if (viewMode !== ViewMode.EDIT) return; + const allBadges: TopNavMenuProps['badges'] = []; + if (hasUnsavedChanges) { + allBadges.push({ + 'data-test-subj': 'dashboardUnsavedChangesBadge', + badgeText: unsavedChangesBadgeStrings.getUnsavedChangedBadgeText(), + title: '', + color: 'warning', + toolTipProps: { + content: unsavedChangesBadgeStrings.getUnsavedChangedBadgeToolTipContent(), + position: 'bottom', + } as EuiToolTipProps, + }); + } + if (hasRunMigrations) { + allBadges.push({ + 'data-test-subj': 'dashboardSaveRecommendedBadge', + badgeText: unsavedChangesBadgeStrings.getHasRunMigrationsText(), + title: '', + color: 'success', + iconType: 'save', + toolTipProps: { + content: unsavedChangesBadgeStrings.getHasRunMigrationsToolTipContent(), + position: 'bottom', + } as EuiToolTipProps, + }); + } + return allBadges; + }, [hasRunMigrations, hasUnsavedChanges, viewMode]); + return (

    { if (isUpdate === false) { dashboard.forceRefresh(); diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.test.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.test.tsx index 8beba68e51da2..17ea8618ef57c 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.test.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.test.tsx @@ -130,12 +130,9 @@ describe('ShowShareModal', () => { locatorParams: { params: DashboardAppLocatorParams }; } ).locatorParams.params; - const { - initializerContext: { kibanaVersion }, - } = pluginServices.getServices(); const rawDashboardState = { ...unsavedDashboardState, - panels: convertPanelMapToSavedPanels(unsavedDashboardState.panels, kibanaVersion), + panels: convertPanelMapToSavedPanels(unsavedDashboardState.panels), }; unsavedStateKeys.forEach((key) => { expect(shareLocatorParams[key]).toStrictEqual( diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.tsx index eee127d51fdd7..98a899d6cac7f 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.tsx @@ -58,7 +58,6 @@ export function ShowShareModal({ }, }, }, - initializerContext: { kibanaVersion }, share: { toggleShareContextMenu }, } = pluginServices.getServices(); @@ -131,8 +130,7 @@ export function ShowShareModal({ controlGroupInput: unsavedDashboardState.controlGroupInput as SerializableControlGroupInput, panels: unsavedDashboardState.panels ? (convertPanelMapToSavedPanels( - unsavedDashboardState.panels, - kibanaVersion + unsavedDashboardState.panels ) as DashboardAppLocatorParams['panels']) : undefined, diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx index 51fad4a852ef9..ed28b2727ca88 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx @@ -48,6 +48,9 @@ export const useDashboardMenuItems = ({ */ const dashboard = useDashboardAPI(); + const hasRunMigrations = dashboard.select( + (state) => state.componentState.hasRunClientsideMigrations + ); const hasUnsavedChanges = dashboard.select((state) => state.componentState.hasUnsavedChanges); const hasOverlays = dashboard.select((state) => state.componentState.hasOverlays); const lastSavedId = dashboard.select((state) => state.componentState.lastSavedId); @@ -179,7 +182,7 @@ export const useDashboardMenuItems = ({ emphasize: true, isLoading: isSaveInProgress, testId: 'dashboardQuickSaveMenuItem', - disableButton: disableTopNav || !hasUnsavedChanges, + disableButton: disableTopNav || !(hasRunMigrations || hasUnsavedChanges), run: () => quickSaveDashboard(), } as TopNavMenuData, @@ -229,6 +232,7 @@ export const useDashboardMenuItems = ({ }, [ disableTopNav, isSaveInProgress, + hasRunMigrations, hasUnsavedChanges, lastSavedId, showShare, diff --git a/src/plugins/dashboard/public/dashboard_app/url/search_sessions_integration.ts b/src/plugins/dashboard/public/dashboard_app/url/search_sessions_integration.ts index 2cf31c0ec0e03..c66042030bc1c 100644 --- a/src/plugins/dashboard/public/dashboard_app/url/search_sessions_integration.ts +++ b/src/plugins/dashboard/public/dashboard_app/url/search_sessions_integration.ts @@ -77,7 +77,6 @@ function getLocatorParams({ }, search: { session }, }, - initializerContext: { kibanaVersion }, } = pluginServices.getServices(); const { @@ -102,9 +101,6 @@ function getLocatorParams({ : undefined, panels: lastSavedId ? undefined - : (convertPanelMapToSavedPanels( - panels, - kibanaVersion - ) as DashboardAppLocatorParams['panels']), + : (convertPanelMapToSavedPanels(panels) as DashboardAppLocatorParams['panels']), }; } diff --git a/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts b/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts index 6d6872ae73b0f..45574312ec8e0 100644 --- a/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts +++ b/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts @@ -32,7 +32,12 @@ import { migrateLegacyQuery } from '../../services/dashboard_content_management/ */ export const isPanelVersionTooOld = (panels: SavedDashboardPanel[]) => { for (const panel of panels) { - if (!panel.version || semverSatisfies(panel.version, '<7.3')) return true; + if ( + !panel.gridData || + !panel.embeddableConfig || + (panel.version && semverSatisfies(panel.version, '<7.3')) + ) + return true; } return false; }; diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/create/create_dashboard.ts b/src/plugins/dashboard/public/dashboard_container/embeddable/create/create_dashboard.ts index 753b881e5a94e..fad615e481ef9 100644 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/create/create_dashboard.ts +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/create/create_dashboard.ts @@ -91,6 +91,7 @@ export const createDashboard = async ( reduxEmbeddablePackage, searchSessionId, savedObjectResult?.dashboardInput, + savedObjectResult.anyMigrationRun, dashboardCreationStartTime, undefined, creationOptions, diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx index df0e728a16d1b..3027cddd167dd 100644 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx @@ -127,6 +127,7 @@ export class DashboardContainer extends Container ) => { state.componentState.lastSavedInput = action.payload; + + // if we set the last saved input, it means we have saved this Dashboard - therefore clientside migrations have + // been serialized into the SO. + state.componentState.hasRunClientsideMigrations = false; }, /** diff --git a/src/plugins/dashboard/public/dashboard_container/types.ts b/src/plugins/dashboard/public/dashboard_container/types.ts index 8ec0082d4109d..8bcc62a04995a 100644 --- a/src/plugins/dashboard/public/dashboard_container/types.ts +++ b/src/plugins/dashboard/public/dashboard_container/types.ts @@ -31,6 +31,7 @@ export type DashboardStateFromSettingsFlyout = DashboardStateFromSaveModal & Das export interface DashboardPublicState { lastSavedInput: DashboardContainerInput; + hasRunClientsideMigrations?: boolean; animatePanelTransforms?: boolean; isEmbeddedExternally?: boolean; hasUnsavedChanges?: boolean; 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/dashboard_content_management/lib/dashboard_versioning.ts b/src/plugins/dashboard/public/services/dashboard_content_management/lib/dashboard_versioning.ts new file mode 100644 index 0000000000000..a1d5fa45e1c43 --- /dev/null +++ b/src/plugins/dashboard/public/services/dashboard_content_management/lib/dashboard_versioning.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. + */ + +/** + * since version is saved as a number for BWC reasons, we need to convert the semver version to a number before + * saving it. For the time being we can just remove the minor and patch version info. + */ +export const convertDashboardVersionToNumber = (dashboardSemver: string) => { + return +dashboardSemver.split('.')[0]; +}; + +/** + * since version is saved as a number for BWC reasons, we need to convert the numeric version to a semver version. For the + * time being we can just convert the numeric version into the MAJOR version of a semver string. + */ +export const convertNumberToDashboardVersion = (numericVersion: number) => `${numericVersion}.0.0`; diff --git a/src/plugins/dashboard/public/services/dashboard_content_management/lib/load_dashboard_state.ts b/src/plugins/dashboard/public/services/dashboard_content_management/lib/load_dashboard_state.ts index 538162a8eacbc..bb4a2a9a83345 100644 --- a/src/plugins/dashboard/public/services/dashboard_content_management/lib/load_dashboard_state.ts +++ b/src/plugins/dashboard/public/services/dashboard_content_management/lib/load_dashboard_state.ts @@ -20,9 +20,11 @@ import { type DashboardOptions, convertSavedPanelsToPanelMap, } from '../../../../common'; +import { migrateDashboardInput } from './migrate_dashboard_input'; import { DashboardCrudTypes } from '../../../../common/content_management'; import type { LoadDashboardFromSavedObjectProps, LoadDashboardReturn } from '../types'; import { DASHBOARD_CONTENT_ID, DEFAULT_DASHBOARD_INPUT } from '../../../dashboard_constants'; +import { convertNumberToDashboardVersion } from './dashboard_versioning'; export function migrateLegacyQuery(query: Query | { [key: string]: any } | string): Query { // Lucene was the only option before, so language-less queries are all lucene @@ -66,6 +68,7 @@ export const loadDashboardState = async ({ .catch((e) => { throw new SavedObjectNotFound(DASHBOARD_CONTENT_ID, id); }); + if (!rawDashboardContent || !rawDashboardContent.version) { return { dashboardInput: newDashboardState, @@ -118,6 +121,7 @@ export const loadDashboardState = async ({ optionsJSON, panelsJSON, timeFrom, + version, timeTo, title, } = attributes; @@ -136,11 +140,8 @@ export const loadDashboardState = async ({ const options: DashboardOptions = optionsJSON ? JSON.parse(optionsJSON) : undefined; const panels = convertSavedPanelsToPanelMap(panelsJSON ? JSON.parse(panelsJSON) : []); - return { - resolveMeta, - dashboardFound: true, - dashboardId: savedObjectId, - dashboardInput: { + const { dashboardInput, anyMigrationRun } = migrateDashboardInput( + { ...DEFAULT_DASHBOARD_INPUT, ...options, @@ -160,6 +161,17 @@ export const loadDashboardState = async ({ controlGroupInput: attributes.controlGroupInput && rawControlGroupAttributesToControlGroupInput(attributes.controlGroupInput), + + version: convertNumberToDashboardVersion(version), }, + embeddable + ); + + return { + resolveMeta, + dashboardInput, + anyMigrationRun, + dashboardFound: true, + dashboardId: savedObjectId, }; }; diff --git a/src/plugins/dashboard/public/services/dashboard_content_management/lib/migrate_dashboard_input.test.ts b/src/plugins/dashboard/public/services/dashboard_content_management/lib/migrate_dashboard_input.test.ts new file mode 100644 index 0000000000000..10c7c5c40b587 --- /dev/null +++ b/src/plugins/dashboard/public/services/dashboard_content_management/lib/migrate_dashboard_input.test.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ControlGroupInput } from '@kbn/controls-plugin/common'; +import { controlGroupInputBuilder } from '@kbn/controls-plugin/public'; + +import { DashboardContainerInput } from '../../../../common'; +import { migrateDashboardInput } from './migrate_dashboard_input'; +import { DashboardEmbeddableService } from '../../embeddable/types'; +import { getSampleDashboardInput, getSampleDashboardPanel } from '../../../mocks'; + +jest.mock('@kbn/embeddable-plugin/public', () => { + return { + ...jest.requireActual('@kbn/embeddable-plugin/public'), + runEmbeddableFactoryMigrations: jest + .fn() + .mockImplementation((input) => ({ input, migrationRun: true })), + }; +}); + +describe('Migrate dashboard input', () => { + it('should run factory migrations on all Dashboard content', () => { + const dashboardInput: DashboardContainerInput = getSampleDashboardInput(); + dashboardInput.panels = { + panel1: getSampleDashboardPanel({ type: 'superLens', explicitInput: { id: 'panel1' } }), + panel2: getSampleDashboardPanel({ type: 'superLens', explicitInput: { id: 'panel2' } }), + panel3: getSampleDashboardPanel({ type: 'ultraDiscover', explicitInput: { id: 'panel3' } }), + panel4: getSampleDashboardPanel({ type: 'ultraDiscover', explicitInput: { id: 'panel4' } }), + }; + const controlGroupInput = { chainingSystem: 'NONE', panels: {} } as ControlGroupInput; + controlGroupInputBuilder.addOptionsListControl(controlGroupInput, { + dataViewId: 'positions-remain-fixed', + title: 'Results can be mixed', + fieldName: 'theres-a-stasis', + width: 'medium', + grow: false, + }); + controlGroupInputBuilder.addRangeSliderControl(controlGroupInput, { + dataViewId: 'an-object-set-in-motion', + title: 'The arbiter of time', + fieldName: 'unexpressed-emotion', + width: 'medium', + grow: false, + }); + controlGroupInputBuilder.addTimeSliderControl(controlGroupInput); + dashboardInput.controlGroupInput = controlGroupInput; + + const embeddableService: DashboardEmbeddableService = { + getEmbeddableFactory: jest.fn(() => ({ + latestVersion: '1.0.0', + migrations: {}, + })), + } as unknown as DashboardEmbeddableService; + + const result = migrateDashboardInput(dashboardInput, embeddableService); + + // migration run should be true because the runEmbeddableFactoryMigrations mock above returns true. + expect(result.anyMigrationRun).toBe(true); + + expect(embeddableService.getEmbeddableFactory).toHaveBeenCalledTimes(7); // should be called 4 times for the panels, and 3 times for the controls + expect(embeddableService.getEmbeddableFactory).toHaveBeenCalledWith('superLens'); + expect(embeddableService.getEmbeddableFactory).toHaveBeenCalledWith('ultraDiscover'); + expect(embeddableService.getEmbeddableFactory).toHaveBeenCalledWith('optionsListControl'); + expect(embeddableService.getEmbeddableFactory).toHaveBeenCalledWith('rangeSliderControl'); + expect(embeddableService.getEmbeddableFactory).toHaveBeenCalledWith('timeSlider'); + }); +}); diff --git a/src/plugins/dashboard/public/services/dashboard_content_management/lib/migrate_dashboard_input.ts b/src/plugins/dashboard/public/services/dashboard_content_management/lib/migrate_dashboard_input.ts new file mode 100644 index 0000000000000..57da6e85618fd --- /dev/null +++ b/src/plugins/dashboard/public/services/dashboard_content_management/lib/migrate_dashboard_input.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + runEmbeddableFactoryMigrations, + EmbeddableFactoryNotFoundError, +} from '@kbn/embeddable-plugin/public'; +import { ControlGroupInput } from '@kbn/controls-plugin/common'; + +import { type DashboardEmbeddableService } from '../../embeddable/types'; +import { DashboardContainerInput, DashboardPanelState } from '../../../../common'; + +/** + * Run Dashboard migrations clientside. We pre-emptively run all migrations for all content on this Dashboard so that + * we can ensure the `last saved state` which eventually resides in the Dashboard public state is fully migrated. + * This prevents the reset button from un-migrating the panels on the Dashboard. This also means that the migrations may + * get skipped at Embeddable create time - unless states with older versions are saved in the URL or session storage. + */ +export const migrateDashboardInput = ( + dashboardInput: DashboardContainerInput, + embeddable: DashboardEmbeddableService +) => { + let anyMigrationRun = false; + if (!dashboardInput) return dashboardInput; + if (dashboardInput.controlGroupInput) { + /** + * If any Control Group migrations are required, we will need to start storing a Control Group Input version + * string in Dashboard Saved Objects and then running the whole Control Group input through the embeddable + * factory migrations here. + */ + + // Migrate all of the Control children as well. + const migratedControls: ControlGroupInput['panels'] = {}; + + Object.entries(dashboardInput.controlGroupInput.panels).forEach(([id, panel]) => { + const factory = embeddable.getEmbeddableFactory(panel.type); + if (!factory) throw new EmbeddableFactoryNotFoundError(panel.type); + const { input: newInput, migrationRun: controlMigrationRun } = runEmbeddableFactoryMigrations( + panel.explicitInput, + factory + ); + if (controlMigrationRun) anyMigrationRun = true; + panel.explicitInput = newInput as DashboardPanelState['explicitInput']; + migratedControls[id] = panel; + }); + } + const migratedPanels: DashboardContainerInput['panels'] = {}; + Object.entries(dashboardInput.panels).forEach(([id, panel]) => { + const factory = embeddable.getEmbeddableFactory(panel.type); + if (!factory) throw new EmbeddableFactoryNotFoundError(panel.type); + // run last saved migrations for by value panels only. + if (!panel.explicitInput.savedObjectId) { + const { input: newInput, migrationRun: panelMigrationRun } = runEmbeddableFactoryMigrations( + panel.explicitInput, + factory + ); + if (panelMigrationRun) anyMigrationRun = true; + panel.explicitInput = newInput as DashboardPanelState['explicitInput']; + } else if (factory.latestVersion) { + // by reference panels are always considered to be of the latest version + panel.explicitInput.version = factory.latestVersion; + } + migratedPanels[id] = panel; + }); + dashboardInput.panels = migratedPanels; + return { dashboardInput, anyMigrationRun }; +}; diff --git a/src/plugins/dashboard/public/services/dashboard_content_management/lib/save_dashboard_state.ts b/src/plugins/dashboard/public/services/dashboard_content_management/lib/save_dashboard_state.ts index 60d1a0f8972e0..7f0ed1e8305cd 100644 --- a/src/plugins/dashboard/public/services/dashboard_content_management/lib/save_dashboard_state.ts +++ b/src/plugins/dashboard/public/services/dashboard_content_management/lib/save_dashboard_state.ts @@ -29,8 +29,10 @@ import { } from '../types'; import { DashboardStartDependencies } from '../../../plugin'; import { DASHBOARD_CONTENT_ID } from '../../../dashboard_constants'; +import { LATEST_DASHBOARD_CONTAINER_VERSION } from '../../../dashboard_container'; import { DashboardCrudTypes, DashboardAttributes } from '../../../../common/content_management'; import { dashboardSaveToastStrings } from '../../../dashboard_container/_dashboard_container_strings'; +import { convertDashboardVersionToNumber } from './dashboard_versioning'; export const serializeControlGroupInput = ( controlGroupInput: DashboardContainerInput['controlGroupInput'] @@ -75,7 +77,6 @@ export const saveDashboardState = async ({ savedObjectsTagging, dashboardSessionStorage, notifications: { toasts }, - initializerContext: { kibanaVersion }, }: SaveDashboardStateProps): Promise => { const { search: dataSearchService, @@ -90,6 +91,7 @@ export const saveDashboardState = async ({ title, panels, filters, + version, timeRestore, description, controlGroupInput, @@ -128,7 +130,7 @@ export const saveDashboardState = async ({ syncTooltips, hidePanelTitles, }); - const panelsJSON = JSON.stringify(convertPanelMapToSavedPanels(panels, kibanaVersion)); + const panelsJSON = JSON.stringify(convertPanelMapToSavedPanels(panels, true)); /** * Parse global time filter settings @@ -146,6 +148,7 @@ export const saveDashboardState = async ({ : undefined; const rawDashboardAttributes: DashboardAttributes = { + version: convertDashboardVersionToNumber(version ?? LATEST_DASHBOARD_CONTAINER_VERSION), controlGroupInput: serializeControlGroupInput(controlGroupInput), kibanaSavedObjectMeta: { searchSourceJSON }, description: description ?? '', @@ -156,7 +159,6 @@ export const saveDashboardState = async ({ timeFrom, title, timeTo, - version: 1, // todo - where does version come from? Why is it needed? }; /** @@ -169,6 +171,7 @@ export const saveDashboardState = async ({ }, { embeddablePersistableStateService: embeddable } ); + const references = savedObjectsTagging.updateTagsReferences ? savedObjectsTagging.updateTagsReferences(dashboardReferences, tags) : dashboardReferences; diff --git a/src/plugins/dashboard/public/services/dashboard_content_management/types.ts b/src/plugins/dashboard/public/services/dashboard_content_management/types.ts index 41e1ce55f979f..288f8d4143f76 100644 --- a/src/plugins/dashboard/public/services/dashboard_content_management/types.ts +++ b/src/plugins/dashboard/public/services/dashboard_content_management/types.ts @@ -66,6 +66,7 @@ export interface LoadDashboardReturn { dashboardId?: string; resolveMeta?: DashboardResolveMeta; dashboardInput: DashboardContainerInput; + anyMigrationRun?: boolean; } /** 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/dashboard/public/services/no_data_page/types.ts b/src/plugins/dashboard/public/services/no_data_page/types.ts new file mode 100644 index 0000000000000..7e87f1586db33 --- /dev/null +++ b/src/plugins/dashboard/public/services/no_data_page/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. + */ + +import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public'; + +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/server/content_management/dashboard_storage.ts b/src/plugins/dashboard/server/content_management/dashboard_storage.ts index 80e2e134dd018..fbbfa0ef26a47 100644 --- a/src/plugins/dashboard/server/content_management/dashboard_storage.ts +++ b/src/plugins/dashboard/server/content_management/dashboard_storage.ts @@ -46,6 +46,7 @@ export class DashboardStorage extends SOContentStorage { 'optionsJSON', 'panelsJSON', 'timeFrom', + 'version', 'timeTo', 'title', ], diff --git a/src/plugins/dashboard/server/dashboard_saved_object/migrations/migrate_by_value_dashboard_panels.ts b/src/plugins/dashboard/server/dashboard_saved_object/migrations/migrate_by_value_dashboard_panels.ts index 1b671112e1b1e..9f768f8d51910 100644 --- a/src/plugins/dashboard/server/dashboard_saved_object/migrations/migrate_by_value_dashboard_panels.ts +++ b/src/plugins/dashboard/server/dashboard_saved_object/migrations/migrate_by_value_dashboard_panels.ts @@ -74,15 +74,13 @@ export const migrateByValueDashboardPanels = type: originalPanelState.type, }); // Convert the embeddable state back into the panel shape - newPanels.push( - convertPanelStateToSavedDashboardPanel( - { - ...originalPanelState, - explicitInput: { ...migratedInput, id: migratedInput.id as string }, - }, - version - ) - ); + newPanels.push({ + ...convertPanelStateToSavedDashboardPanel({ + ...originalPanelState, + explicitInput: { ...migratedInput, id: migratedInput.id as string }, + }), + version, + }); } else { newPanels.push(panel); } diff --git a/src/plugins/dashboard/server/dashboard_saved_object/migrations/migrate_hidden_titles.ts b/src/plugins/dashboard/server/dashboard_saved_object/migrations/migrate_hidden_titles.ts index d071a094ac19c..61ad21904802f 100644 --- a/src/plugins/dashboard/server/dashboard_saved_object/migrations/migrate_hidden_titles.ts +++ b/src/plugins/dashboard/server/dashboard_saved_object/migrations/migrate_hidden_titles.ts @@ -37,19 +37,16 @@ export const migrateExplicitlyHiddenTitles: SavedObjectMigrationFn = ( // Convert each panel into the dashboard panel state const originalPanelState = convertSavedDashboardPanelToPanelState(panel); newPanels.push( - convertPanelStateToSavedDashboardPanel( - { - ...originalPanelState, - explicitInput: { - ...originalPanelState.explicitInput, - ...(originalPanelState.explicitInput.title === '' && - !originalPanelState.explicitInput.hidePanelTitles - ? { hidePanelTitles: true } - : {}), - }, + convertPanelStateToSavedDashboardPanel({ + ...originalPanelState, + explicitInput: { + ...originalPanelState.explicitInput, + ...(originalPanelState.explicitInput.title === '' && + !originalPanelState.explicitInput.hidePanelTitles + ? { hidePanelTitles: true } + : {}), }, - panel.version - ) + }) ); }); return { 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/index.ts b/src/plugins/data/common/index.ts index 0d2fce23109f0..a7a5263229ddc 100644 --- a/src/plugins/data/common/index.ts +++ b/src/plugins/data/common/index.ts @@ -13,6 +13,7 @@ export { DEFAULT_QUERY_LANGUAGE, KIBANA_USER_QUERY_LANGUAGE_KEY, KQL_TELEMETRY_ROUTE_LATEST_VERSION, + SAVED_QUERY_BASE_URL, SCRIPT_LANGUAGES_ROUTE_LATEST_VERSION, UI_SETTINGS, } from './constants'; 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/query/types.ts b/src/plugins/data/common/query/types.ts index e10afaf746455..e6270e3c81ca3 100644 --- a/src/plugins/data/common/query/types.ts +++ b/src/plugins/data/common/query/types.ts @@ -19,6 +19,7 @@ export type SavedQueryTimeFilter = TimeRange & { export interface SavedQuery { id: string; attributes: SavedQueryAttributes; + namespaces: string[]; } export interface SavedQueryAttributes { 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/poll_search.test.ts b/src/plugins/data/common/search/poll_search.test.ts index dbb8e5137de21..db39b5e187036 100644 --- a/src/plugins/data/common/search/poll_search.test.ts +++ b/src/plugins/data/common/search/poll_search.test.ts @@ -83,7 +83,7 @@ describe('pollSearch', () => { abortSignal: abortController.signal, }).toPromise(); - await new Promise((resolve) => setTimeout(resolve, 500)); + await new Promise((resolve) => setTimeout(resolve, 300)); abortController.abort(); await expect(poll).rejects.toThrow(AbortError); @@ -99,7 +99,7 @@ describe('pollSearch', () => { const cancelFn = jest.fn(); const subscription = pollSearch(searchFn, cancelFn).subscribe(() => {}); - await new Promise((resolve) => setTimeout(resolve, 500)); + await new Promise((resolve) => setTimeout(resolve, 300)); subscription.unsubscribe(); await new Promise((resolve) => setTimeout(resolve, 1000)); diff --git a/src/plugins/data/common/search/poll_search.ts b/src/plugins/data/common/search/poll_search.ts index a58fad3880c69..1a6819257ab67 100644 --- a/src/plugins/data/common/search/poll_search.ts +++ b/src/plugins/data/common/search/poll_search.ts @@ -22,6 +22,8 @@ export const pollSearch = ( else { // if static pollInterval is not provided, then use default back-off logic switch (true) { + case elapsedTime < 1500: + return 300; case elapsedTime < 5000: return 1000; case elapsedTime < 20000: diff --git a/src/plugins/data/common/search/search_source/create_search_source.test.ts b/src/plugins/data/common/search/search_source/create_search_source.test.ts index 491673dc8ebca..709b065c1ec41 100644 --- a/src/plugins/data/common/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/common/search/search_source/create_search_source.test.ts @@ -23,6 +23,7 @@ describe('createSearchSource', () => { getConfig: jest.fn(), search: jest.fn(), onResponse: (req, res) => res, + scriptedFieldsEnabled: true, }; indexPatternContractMock = { diff --git a/src/plugins/data/common/search/search_source/mocks.ts b/src/plugins/data/common/search/search_source/mocks.ts index a980004bd1ceb..6bcd2a76d9aca 100644 --- a/src/plugins/data/common/search/search_source/mocks.ts +++ b/src/plugins/data/common/search/search_source/mocks.ts @@ -71,4 +71,5 @@ export const createSearchSourceMock = ( ) ), onResponse: jest.fn().mockImplementation((req, res) => res), + scriptedFieldsEnabled: true, }); 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 f4146cc5634de..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 @@ -94,6 +94,7 @@ describe('SearchSource', () => { getConfig: getConfigMock, search: mockSearchMethod, onResponse: jest.fn().mockImplementation((_, res) => res), + scriptedFieldsEnabled: true, }; searchSource = new SearchSource({}, searchSourceDependencies); @@ -651,6 +652,22 @@ describe('SearchSource', () => { const request = searchSource.getSearchRequestBody(); expect(request.script_fields).toEqual({ hello: {}, world: {} }); }); + + test('ignores scripted fields when scripted fields are disabled', async () => { + searchSource.setField('index', { + ...indexPattern, + getComputedFields: () => ({ + storedFields: [], + scriptFields: { hello: {}, world: {} }, + docvalueFields: [], + }), + } as unknown as DataView); + searchSourceDependencies.scriptedFieldsEnabled = false; + searchSource.setField('fields', ['timestamp', '*']); + + const request = searchSource.getSearchRequestBody(); + expect(request.script_fields).toEqual({}); + }); }); describe('handling for when specific fields are provided', () => { @@ -1088,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 a9d48108d296d..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, @@ -138,6 +137,7 @@ export const searchSourceRequiredUiSettings = [ export interface SearchSourceDependencies extends FetchHandlers { aggs: AggsStart; search: ISearchGeneric; + scriptedFieldsEnabled: boolean; } interface ExpressionAstOptions { @@ -546,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()) { @@ -798,10 +796,12 @@ export class SearchSource { // set defaults let fieldsFromSource = searchRequest.fieldsFromSource || []; body.fields = body.fields || []; - body.script_fields = { - ...body.script_fields, - ...scriptFields, - }; + body.script_fields = this.dependencies.scriptedFieldsEnabled + ? { + ...body.script_fields, + ...scriptFields, + } + : {}; body.stored_fields = storedFields; body.runtime_mappings = runtimeFields || {}; @@ -918,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: [ // { @@ -930,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/search_source/search_source_service.test.ts b/src/plugins/data/common/search/search_source/search_source_service.test.ts index 70448db335a07..8e03f56fe0421 100644 --- a/src/plugins/data/common/search/search_source/search_source_service.test.ts +++ b/src/plugins/data/common/search/search_source/search_source_service.test.ts @@ -19,6 +19,7 @@ describe('SearchSource service', () => { getConfig: jest.fn(), search: jest.fn(), onResponse: jest.fn(), + scriptedFieldsEnabled: true, }; }); 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/data/common/search/strategies/esql_search/types.ts b/src/plugins/data/common/search/strategies/esql_search/types.ts new file mode 100644 index 0000000000000..d71da852e55de --- /dev/null +++ b/src/plugins/data/common/search/strategies/esql_search/types.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 const ESQL_SEARCH_STRATEGY = 'esql'; diff --git a/src/plugins/data/config.ts b/src/plugins/data/config.ts index 688f65038aa11..03cd77653becb 100644 --- a/src/plugins/data/config.ts +++ b/src/plugins/data/config.ts @@ -55,7 +55,7 @@ export const searchConfigSchema = schema.object({ * Block and wait until the search is completed up to the timeout (see es async_search's `wait_for_completion_timeout`) * TODO: we should optimize this as 100ms is likely not optimal (https://github.com/elastic/kibana/issues/143277) */ - waitForCompletion: schema.duration({ defaultValue: '100ms' }), + waitForCompletion: schema.duration({ defaultValue: '200ms' }), /** * How long the async search needs to be available after each search poll. Ongoing async searches and any saved search results are deleted after this period. * (see es async_search's `keep_alive`) @@ -71,7 +71,7 @@ export const searchConfigSchema = schema.object({ * How long to wait before polling the async_search after the previous poll response. * If not provided, then default dynamic interval with backoff is used. */ - pollInterval: schema.maybe(schema.number({ min: 1000 })), + pollInterval: schema.maybe(schema.number({ min: 200 })), }), aggs: schema.object({ shardDelay: schema.object({ 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 8f4e37afb29b2..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, @@ -138,6 +139,7 @@ export class DataPublicPlugin fieldFormats, indexPatterns: dataViews, screenshotMode, + scriptedFieldsEnabled: dataViews.scriptedFieldsEnabled, }); setSearchService(search); @@ -167,6 +169,7 @@ export class DataPublicPlugin actions: { createFiltersFromValueClickAction, createFiltersFromRangeSelectAction, + createFiltersFromMultiValueClickAction, }, datatableUtilities, fieldFormats, diff --git a/src/plugins/data/public/query/saved_query/types.ts b/src/plugins/data/public/query/saved_query/types.ts index eac7bd3aa30b1..7b6b7408b4369 100644 --- a/src/plugins/data/public/query/saved_query/types.ts +++ b/src/plugins/data/public/query/saved_query/types.ts @@ -6,25 +6,15 @@ * Side Public License, v 1. */ -import type { TimeRange, Query, Filter } from '@kbn/es-query'; +import type { TimeRange } from '@kbn/es-query'; import { RefreshInterval } from '../..'; +import { SavedQuery, SavedQueryAttributes } from '../../../common/types'; export type SavedQueryTimeFilter = TimeRange & { refreshInterval: RefreshInterval; }; -export interface SavedQuery { - id: string; - attributes: SavedQueryAttributes; -} - -export interface SavedQueryAttributes { - title: string; - description: string; - query: Query; - filters?: Filter[]; - timefilter?: SavedQueryTimeFilter; -} +export type { SavedQuery, SavedQueryAttributes }; export interface SavedQueryService { createQuery: (attributes: SavedQueryAttributes) => Promise; 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.test.ts b/src/plugins/data/public/search/search_service.test.ts index a64b90772900a..c94cde6b8f747 100644 --- a/src/plugins/data/public/search/search_service.test.ts +++ b/src/plugins/data/public/search/search_service.test.ts @@ -69,6 +69,7 @@ describe('Search service', () => { fieldFormats: {} as FieldFormatsStart, indexPatterns: {} as DataViewsContract, screenshotMode: screenshotModePluginMock.createStartContract(), + scriptedFieldsEnabled: true, }); }); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index d9033e0eed5f1..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'; @@ -86,6 +86,7 @@ export interface SearchServiceStartDependencies { fieldFormats: FieldFormatsStart; indexPatterns: DataViewsContract; screenshotMode: ScreenshotModePluginStart; + scriptedFieldsEnabled: boolean; } export class SearchService implements Plugin { @@ -172,6 +173,11 @@ export class SearchService implements Plugin { getStartServices: StartServicesAccessor; }) ); + expressions.registerFunction( + getEsql({ getStartServices } as { + getStartServices: StartServicesAccessor; + }) + ); expressions.registerFunction( getEql({ getStartServices } as { getStartServices: StartServicesAccessor; @@ -216,7 +222,12 @@ export class SearchService implements Plugin { public start( { http, theme, uiSettings, chrome, application }: CoreStart, - { fieldFormats, indexPatterns, screenshotMode }: SearchServiceStartDependencies + { + fieldFormats, + indexPatterns, + screenshotMode, + scriptedFieldsEnabled, + }: SearchServiceStartDependencies ): ISearchStart { const search = ((request, options = {}) => { return this.searchInterceptor.search(request, options); @@ -245,6 +256,7 @@ export class SearchService implements Plugin { } return response; }, + scriptedFieldsEnabled, }; const config = this.initializerContext.config.get(); 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/query/route_handler_context.test.ts b/src/plugins/data/server/query/route_handler_context.test.ts index 1c274fcfc3953..08052944cb283 100644 --- a/src/plugins/data/server/query/route_handler_context.test.ts +++ b/src/plugins/data/server/query/route_handler_context.test.ts @@ -553,7 +553,7 @@ describe('saved query route handler context', () => { describe('delete', function () { it('should delete the saved query for the given ID', async () => { await context.delete('foo'); - expect(mockSavedObjectsClient.delete).toHaveBeenCalledWith('query', 'foo'); + expect(mockSavedObjectsClient.delete).toHaveBeenCalledWith('query', 'foo', { force: true }); }); }); diff --git a/src/plugins/data/server/query/route_handler_context.ts b/src/plugins/data/server/query/route_handler_context.ts index 6179a909eee57..fcca59ece59fd 100644 --- a/src/plugins/data/server/query/route_handler_context.ts +++ b/src/plugins/data/server/query/route_handler_context.ts @@ -14,8 +14,9 @@ import { extract, inject } from '../../common/query/filters/persistable_state'; function injectReferences({ id, attributes, + namespaces, references, -}: Pick, 'id' | 'attributes' | 'references'>) { +}: Pick, 'id' | 'attributes' | 'namespaces' | 'references'>) { const { query } = attributes; if (isOfQueryType(query) && typeof query.query === 'string') { try { @@ -26,7 +27,7 @@ function injectReferences({ } } const filters = inject(attributes.filters ?? [], references); - return { id, attributes: { ...attributes, filters } }; + return { id, attributes: { ...attributes, filters }, namespaces }; } function extractReferences({ @@ -156,7 +157,7 @@ export async function registerSavedQueryRouteHandlerContext(context: RequestHand }; const deleteSavedQuery = async (id: string) => { - return await soClient.delete('query', id); + return await soClient.delete('query', id, { force: true }); }; return { diff --git a/src/plugins/data/server/query/routes.ts b/src/plugins/data/server/query/routes.ts index a092a32d321a5..7446e3ad83a12 100644 --- a/src/plugins/data/server/query/routes.ts +++ b/src/plugins/data/server/query/routes.ts @@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema'; import { CoreSetup } from '@kbn/core/server'; +import { reportServerError } from '@kbn/kibana-utils-plugin/server'; import { SavedQueryRouteHandlerContext } from './route_handler_context'; import { SavedQueryRestResponse } from './route_types'; import { SAVED_QUERY_BASE_URL } from '../../common/constants'; @@ -29,6 +30,7 @@ const SAVED_QUERY_ATTRS_CONFIG = schema.object({ const savedQueryResponseSchema = schema.object({ id: schema.string(), attributes: SAVED_QUERY_ATTRS_CONFIG, + namespaces: schema.arrayOf(schema.string()), }); const access = 'internal'; @@ -57,8 +59,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void { const body: SavedQueryRestResponse = await savedQuery.create(request.body); return response.ok({ body }); } catch (e) { - // TODO: Handle properly - return response.customError(e); + const err = e.output?.payload ?? e; + return reportServerError(response, err); } } ); @@ -85,8 +87,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void { const body: SavedQueryRestResponse = await savedQuery.update(id, request.body); return response.ok({ body }); } catch (e) { - // TODO: Handle properly - return response.customError(e); + const err = e.output?.payload ?? e; + return reportServerError(response, err); } } ); @@ -112,8 +114,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void { const body: SavedQueryRestResponse = await savedQuery.get(id); return response.ok({ body }); } catch (e) { - // TODO: Handle properly - return response.customError(e); + const err = e.output?.payload ?? e; + return reportServerError(response, err); } } ); @@ -136,8 +138,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void { const count: number = await savedQuery.count(); return response.ok({ body: `${count}` }); } catch (e) { - // TODO: Handle properly - return response.customError(e); + const err = e.output?.payload ?? e; + return reportServerError(response, err); } } ); @@ -170,8 +172,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void { await savedQuery.find(request.body); return response.ok({ body }); } catch (e) { - // TODO: Handle properly - return response.customError(e); + const err = e.output?.payload ?? e; + return reportServerError(response, err); } } ); @@ -198,8 +200,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void { await savedQuery.getAll(); return response.ok({ body }); } catch (e) { - // TODO: Handle properly - return response.customError(e); + const err = e.output?.payload ?? e; + return reportServerError(response, err); } } ); @@ -225,8 +227,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void { await savedQuery.delete(id); return response.ok(); } catch (e) { - // TODO: Handle properly - return response.customError(e); + const err = e.output?.payload ?? e; + return reportServerError(response, err); } } ); diff --git a/src/plugins/data/server/saved_objects/query.ts b/src/plugins/data/server/saved_objects/query.ts index f59adbbef8750..59ff2483fbefb 100644 --- a/src/plugins/data/server/saved_objects/query.ts +++ b/src/plugins/data/server/saved_objects/query.ts @@ -15,7 +15,7 @@ export const querySavedObjectType: SavedObjectsType = { name: 'query', indexPattern: ANALYTICS_SAVED_OBJECT_INDEX, hidden: false, - namespaceType: 'multiple-isolated', + namespaceType: 'multiple', convertToMultiNamespaceTypeVersion: '8.0.0', management: { icon: 'search', 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 0387cb820f165..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); @@ -302,6 +306,7 @@ export class SearchService implements Plugin { getConfig: (key: string): T => uiSettingsCache[key], search: this.asScoped(request).search, onResponse: (req, res) => res, + scriptedFieldsEnabled: true, }; return this.searchSourceService.start(scopedIndexPatterns, searchSourceDependencies); 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/public/components/edit_index_pattern/tabs/tabs.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx index 075869ab6fdc2..4d18244d6476c 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx @@ -569,7 +569,7 @@ export function Tabs({ const euiTabs: EuiTabbedContentTab[] = useMemo( () => - getTabs(indexPattern, fieldFilter, relationships.length).map( + getTabs(indexPattern, fieldFilter, relationships.length, dataViews.scriptedFieldsEnabled).map( (tab: Pick) => { return { ...tab, @@ -577,7 +577,7 @@ export function Tabs({ }; } ), - [fieldFilter, getContent, indexPattern, relationships] + [fieldFilter, getContent, indexPattern, relationships, dataViews.scriptedFieldsEnabled] ); const [selectedTabId, setSelectedTabId] = useState(euiTabs[0].id); diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/utils.ts b/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/utils.ts index 00b08037e52fe..1c372e13dbe4b 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/utils.ts +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/utils.ts @@ -15,7 +15,7 @@ import { TAB_SOURCE_FILTERS, TAB_RELATIONSHIPS, } from '../constants'; -import { areScriptedFieldsEnabled } from '../../utils'; +import { isRollup } from '../../utils'; function filterByName(items: DataViewField[], filter: string) { const lowercaseFilter = (filter || '').toLowerCase(); @@ -73,7 +73,12 @@ function getTitle(type: string, filteredCount: Dictionary, totalCount: D return title + count; } -export function getTabs(indexPattern: DataView, fieldFilter: string, relationshipCount = 0) { +export function getTabs( + indexPattern: DataView, + fieldFilter: string, + relationshipCount = 0, + scriptedFieldsEnabled: boolean +) { const totalCount = getCounts(indexPattern.fields.getAll(), indexPattern.getSourceFiltering()); const filteredCount = getCounts( indexPattern.fields.getAll(), @@ -89,7 +94,7 @@ export function getTabs(indexPattern: DataView, fieldFilter: string, relationshi 'data-test-subj': 'tab-indexedFields', }); - if (areScriptedFieldsEnabled(indexPattern)) { + if (!isRollup(indexPattern.type) && scriptedFieldsEnabled) { tabs.push({ name: getTitle('scripted', filteredCount, totalCount), id: TAB_SCRIPTED_FIELDS, diff --git a/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx index f2ab10098e4d6..0d0215e6342d7 100644 --- a/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -213,7 +213,10 @@ export const IndexPatternTable = ({ width: '70%', render: (name: string, dataView: IndexPatternTableItem) => (
    - + {dataView.getName()} {dataView.name ? ( <> diff --git a/src/plugins/data_view_management/public/components/utils.ts b/src/plugins/data_view_management/public/components/utils.ts index 5ba434048dc4d..722ad5059a598 100644 --- a/src/plugins/data_view_management/public/components/utils.ts +++ b/src/plugins/data_view_management/public/components/utils.ts @@ -28,7 +28,7 @@ const rollupIndexPatternListName = i18n.translate( } ); -const isRollup = (indexPatternType: string = '') => { +export const isRollup = (indexPatternType: string = '') => { return indexPatternType === 'rollup'; }; @@ -85,10 +85,6 @@ export const getTags = (indexPattern: DataViewListItem | DataView, isDefault: bo return tags; }; -export const areScriptedFieldsEnabled = (indexPattern: DataViewListItem | DataView) => { - return !isRollup(indexPattern.type); -}; - export const getFieldInfo = (indexPattern: DataViewListItem | DataView, field: DataViewField) => { if (!isRollup(indexPattern.type)) { return []; diff --git a/src/plugins/data_view_management/public/management_app/mount_management_section.tsx b/src/plugins/data_view_management/public/management_app/mount_management_section.tsx index d7b21b395fdde..0e3c1758d2992 100644 --- a/src/plugins/data_view_management/public/management_app/mount_management_section.tsx +++ b/src/plugins/data_view_management/public/management_app/mount_management_section.tsx @@ -92,6 +92,10 @@ export async function mountManagementSection( savedObjectsManagement, }; + const editPath = '/dataView/:id/field/:fieldName'; + const createPath = '/dataView/:id/create-field/'; + const createEditPath = dataViews.scriptedFieldsEnabled ? [editPath, createPath] : [editPath]; + ReactDOM.render( @@ -100,7 +104,7 @@ export async function mountManagementSection( - + 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/data_views/common/data_views/data_views.test.ts b/src/plugins/data_views/common/data_views/data_views.test.ts index 2ea7726cc2bb9..5c05832e7b0c4 100644 --- a/src/plugins/data_views/common/data_views/data_views.test.ts +++ b/src/plugins/data_views/common/data_views/data_views.test.ts @@ -115,6 +115,7 @@ describe('IndexPatterns', () => { onRedirectNoIndexPattern: () => {}, getCanSave: () => Promise.resolve(true), getCanSaveAdvancedSettings: () => Promise.resolve(true), + scriptedFieldsEnabled: true, }); indexPatternsNoAccess = new DataViewsService({ @@ -127,6 +128,7 @@ describe('IndexPatterns', () => { onRedirectNoIndexPattern: () => {}, getCanSave: () => Promise.resolve(false), getCanSaveAdvancedSettings: () => Promise.resolve(false), + scriptedFieldsEnabled: true, }); }); diff --git a/src/plugins/data_views/common/data_views/data_views.ts b/src/plugins/data_views/common/data_views/data_views.ts index 9537526046266..7e74a468d3ce8 100644 --- a/src/plugins/data_views/common/data_views/data_views.ts +++ b/src/plugins/data_views/common/data_views/data_views.ts @@ -120,6 +120,8 @@ export interface DataViewsServiceDeps { * Determines whether the user can save advancedSettings (used for defaultIndex) */ getCanSaveAdvancedSettings: () => Promise; + + scriptedFieldsEnabled: boolean; } /** @@ -325,6 +327,8 @@ export class DataViewsService { * Can the user save data views? */ public getCanSave: () => Promise; + + public readonly scriptedFieldsEnabled: boolean; /** * DataViewsService constructor * @param deps Service dependencies @@ -339,6 +343,7 @@ export class DataViewsService { onError, getCanSave = () => Promise.resolve(false), getCanSaveAdvancedSettings, + scriptedFieldsEnabled, } = deps; this.apiClient = apiClient; this.config = uiSettings; @@ -350,6 +355,7 @@ export class DataViewsService { this.getCanSaveAdvancedSettings = getCanSaveAdvancedSettings; this.dataViewCache = createDataViewCache(); + this.scriptedFieldsEnabled = scriptedFieldsEnabled; } /** @@ -591,7 +597,9 @@ export class DataViewsService { private refreshFieldsFn = async (indexPattern: DataView) => { const { fields, indices } = await this.getFieldsAndIndicesForDataView(indexPattern); fields.forEach((field) => (field.isMapped = true)); - const scripted = indexPattern.getScriptedFields().map((field) => field.spec); + const scripted = this.scriptedFieldsEnabled + ? indexPattern.getScriptedFields().map((field) => field.spec) + : []; const fieldAttrs = indexPattern.getFieldAttrs(); const fieldsWithSavedAttrs = Object.values( this.fieldArrayToMap([...fields, ...scripted], fieldAttrs) @@ -655,7 +663,9 @@ export class DataViewsService { displayErrors: boolean = true ) => { const fieldsAsArr = Object.values(fields); - const scriptedFields = fieldsAsArr.filter((field) => field.scripted); + const scriptedFields = this.scriptedFieldsEnabled + ? fieldsAsArr.filter((field) => field.scripted) + : []; try { let updatedFieldList: FieldSpec[]; const { fields: newFields, indices } = await this.getFieldsAndIndicesForWildcard(options); diff --git a/src/plugins/data_views/common/types.ts b/src/plugins/data_views/common/types.ts index 97d76941ea40c..9061c4643dce9 100644 --- a/src/plugins/data_views/common/types.ts +++ b/src/plugins/data_views/common/types.ts @@ -525,3 +525,7 @@ export interface HasDataService { hasUserDataView: () => Promise; hasDataView: () => Promise; } + +export interface ClientConfigType { + scriptedFieldsEnabled?: boolean; +} diff --git a/src/plugins/data_views/docs/openapi/bundled.json b/src/plugins/data_views/docs/openapi/bundled.json index 894e5e02f4564..98ca8cd92daf3 100644 --- a/src/plugins/data_views/docs/openapi/bundled.json +++ b/src/plugins/data_views/docs/openapi/bundled.json @@ -84,6 +84,16 @@ } } } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } } } }, @@ -293,6 +303,85 @@ } ] }, + "/api/data_views/data_view/{viewId}/fields": { + "post": { + "summary": "Update fields presentation metadata such as count, customLabel and format.", + "operationId": "updateFieldsMetadata", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value.\n", + "tags": [ + "data views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/view_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "fields" + ], + "properties": { + "fields": { + "description": "The field object.", + "type": "object" + } + } + }, + "examples": { + "updateFieldsMetadataRequest": { + "$ref": "#/components/examples/update_field_metadata_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "acknowledged": { + "type": "boolean" + } + } + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, "/api/data_views/data_view/{viewId}/runtime_field": { "post": { "summary": "Creates a runtime field.", @@ -304,6 +393,9 @@ "parameters": [ { "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/view_id" } ], "requestBody": { @@ -312,16 +404,18 @@ "application/json": { "schema": { "type": "object", + "required": [ + "name", + "runtimeField" + ], "properties": { - "data_view_id": { - "description": "The ID of the data view.", + "name": { "type": "string", - "required": true + "description": "The name for a runtime field.\n" }, - "space_id": { - "description": "An identifier for the space. If space_id is not provided in the URL, the default space is used.", - "type": "string", - "required": false + "runtimeField": { + "type": "object", + "description": "The runtime field definition object.\n" } } }, @@ -336,7 +430,7 @@ }, "put": { "summary": "Create or update an existing runtime field.", - "operationId": "updateRuntimeField", + "operationId": "createUpdateRuntimeField", "description": "This 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": [ "data views" @@ -344,6 +438,15 @@ "parameters": [ { "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "name": "viewId", + "in": "path", + "description": "The ID of the data view fields you want to update.\n", + "required": true, + "schema": { + "type": "string" + } } ], "requestBody": { @@ -352,16 +455,18 @@ "application/json": { "schema": { "type": "object", + "required": [ + "name", + "runtimeField" + ], "properties": { - "data_view_id": { - "description": "The ID of the data view.", + "name": { "type": "string", - "required": true + "description": "The name for a runtime field.\n" }, - "space_id": { - "description": "An identifier for the space. If space_id is not provided in the URL, the default space is used.", - "type": "string", - "required": false + "runtimeField": { + "type": "object", + "description": "The runtime field definition object.\n" } } }, @@ -379,7 +484,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/create_runtime_field_response" + "type": "object", + "properties": { + "data_view": { + "type": "object" + }, + "fields": { + "type": "array" + } + } + }, + "examples": { + "createRuntimeFieldResponse": { + "$ref": "#/components/examples/create_runtime_field_response" + } } } } @@ -514,15 +632,13 @@ "application/json": { "schema": { "type": "object", + "required": [ + "runtimeField" + ], "properties": { - "data_view": { - "type": "object" - }, - "fields": { - "type": "array", - "items": { - "type": "object" - } + "runtimeField": { + "type": "object", + "description": "The runtime field definition object.\n\nYou can update following fields:\n\n- `type`\n- `script`\n" } } }, @@ -589,6 +705,16 @@ } } } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } } } }, @@ -651,6 +777,16 @@ } } } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/400_response" + } + } + } } }, "servers": [ @@ -1897,6 +2033,16 @@ "refresh_fields": true } }, + "update_field_metadata_request": { + "summary": "Set popularity count for field foo.", + "value": { + "fields": { + "foo": { + "count": 123 + } + } + } + }, "create_runtime_field_request": { "summary": "Create a runtime field.", "value": { @@ -1909,6 +2055,17 @@ } } }, + "create_runtime_field_response": { + "summary": "The API returns created runtime field object array and updated data view object.", + "value": { + "data_view": { + "...": null + }, + "fields": [ + "..." + ] + } + }, "get_runtime_field_response": { "summary": "The get runtime field API returns a JSON object that contains information about the runtime field (`hour_of_day`) and the data view (`d3d7af60-4c81-11e8-b3d7-01146121b73d`).", "value": { @@ -2551,38 +2708,29 @@ } } }, - "parameters": { - "kbn_xsrf": { - "schema": { - "type": "string" - }, - "in": "header", - "name": "kbn-xsrf", - "description": "Cross-site request forgery protection", - "required": true - }, - "view_id": { - "in": "path", - "name": "viewId", - "description": "An identifier for the data view.", - "required": true, - "schema": { - "type": "string", - "example": "ff959d40-b880-11e8-a6d9-e546fe2bba5f" + "schemas": { + "400_response": { + "title": "Bad request", + "type": "object", + "required": [ + "statusCode", + "error", + "message" + ], + "properties": { + "statusCode": { + "type": "number", + "example": 400 + }, + "error": { + "type": "string", + "example": "Bad Request" + }, + "message": { + "type": "string" + } } }, - "field_name": { - "in": "path", - "name": "fieldName", - "description": "The name of the runtime field.", - "required": true, - "schema": { - "type": "string", - "example": "hour_of_day" - } - } - }, - "schemas": { "allownoindex": { "type": "boolean", "description": "Allows the data view saved object to exist before the data is available." @@ -2746,28 +2894,6 @@ } } }, - "400_response": { - "title": "Bad request", - "type": "object", - "required": [ - "statusCode", - "error", - "message" - ], - "properties": { - "statusCode": { - "type": "number", - "example": 400 - }, - "error": { - "type": "string", - "example": "Bad Request" - }, - "message": { - "type": "string" - } - } - }, "404_response": { "type": "object", "properties": { @@ -2840,16 +2966,36 @@ "default": false } } + } + }, + "parameters": { + "kbn_xsrf": { + "schema": { + "type": "string" + }, + "in": "header", + "name": "kbn-xsrf", + "description": "Cross-site request forgery protection", + "required": true }, - "create_runtime_field_response": { - "summary": "The API returns created runtime field object array and updated data view object.", - "value": { - "data_view": { - "...": null - }, - "fields": [ - "..." - ] + "view_id": { + "in": "path", + "name": "viewId", + "description": "An identifier for the data view.", + "required": true, + "schema": { + "type": "string", + "example": "ff959d40-b880-11e8-a6d9-e546fe2bba5f" + } + }, + "field_name": { + "in": "path", + "name": "fieldName", + "description": "The name of the runtime field.", + "required": true, + "schema": { + "type": "string", + "example": "hour_of_day" } } } diff --git a/src/plugins/data_views/docs/openapi/bundled.yaml b/src/plugins/data_views/docs/openapi/bundled.yaml index 7fa381a6a3d02..2fa7eb1cd1550 100644 --- a/src/plugins/data_views/docs/openapi/bundled.yaml +++ b/src/plugins/data_views/docs/openapi/bundled.yaml @@ -54,6 +54,12 @@ paths: examples: getAllDataViewsResponse: $ref: '#/components/examples/get_data_views_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' servers: - url: https://localhost:5601 /api/data_views/data_view: @@ -174,6 +180,52 @@ paths: - url: https://localhost:5601 servers: - url: https://localhost:5601 + /api/data_views/data_view/{viewId}/fields: + post: + summary: Update fields presentation metadata such as count, customLabel and format. + operationId: updateFieldsMetadata + description: | + This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value. + tags: + - data views + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/view_id' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - fields + properties: + fields: + description: The field object. + type: object + examples: + updateFieldsMetadataRequest: + $ref: '#/components/examples/update_field_metadata_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 /api/data_views/data_view/{viewId}/runtime_field: post: summary: Creates a runtime field. @@ -184,48 +236,62 @@ paths: - data views parameters: - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/view_id' requestBody: required: true content: application/json: schema: type: object + required: + - name + - runtimeField properties: - data_view_id: - description: The ID of the data view. - type: string - required: true - space_id: - description: An identifier for the space. If space_id is not provided in the URL, the default space is used. + name: type: string - required: false + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. examples: createRuntimeFieldRequest: $ref: '#/components/examples/create_runtime_field_request' put: summary: Create or update an existing runtime field. - operationId: updateRuntimeField + operationId: createUpdateRuntimeField description: | This 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. tags: - data views parameters: - $ref: '#/components/parameters/kbn_xsrf' + - name: viewId + in: path + description: | + The ID of the data view fields you want to update. + required: true + schema: + type: string requestBody: required: true content: application/json: schema: type: object + required: + - name + - runtimeField properties: - data_view_id: - description: The ID of the data view. - type: string - required: true - space_id: - description: An identifier for the space. If space_id is not provided in the URL, the default space is used. + name: type: string - required: false + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. examples: updateRuntimeFieldRequest: $ref: '#/components/examples/create_runtime_field_request' @@ -235,7 +301,15 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/create_runtime_field_response' + type: object + properties: + data_view: + type: object + fields: + type: array + examples: + createRuntimeFieldResponse: + $ref: '#/components/examples/create_runtime_field_response' '400': description: Bad request content: @@ -315,13 +389,18 @@ paths: application/json: schema: type: object + required: + - runtimeField properties: - data_view: + runtimeField: type: object - fields: - type: array - items: - type: object + description: | + The runtime field definition object. + + You can update following fields: + + - `type` + - `script` examples: updateRuntimeFieldRequest: $ref: '#/components/examples/update_runtime_field_request' @@ -359,6 +438,12 @@ paths: examples: getDefaultDataViewResponse: $ref: '#/components/examples/get_default_data_view_response' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' post: summary: Sets the default data view identifier. operationId: setDefaultDatailView @@ -400,6 +485,12 @@ paths: properties: acknowledged: type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400_response' servers: - url: https://localhost:5601 servers: @@ -1381,6 +1472,12 @@ components: allowNoIndex: false name: Kibana Sample Data eCommerce refresh_fields: true + update_field_metadata_request: + summary: Set popularity count for field foo. + value: + fields: + foo: + count: 123 create_runtime_field_request: summary: Create a runtime field. value: @@ -1389,6 +1486,13 @@ components: type: long script: source: emit(doc["foo"].value) + create_runtime_field_response: + summary: The API returns created runtime field object array and updated data view object. + value: + data_view: + ...: null + fields: + - ... get_runtime_field_response: summary: The get runtime field API returns a JSON object that contains information about the runtime field (`hour_of_day`) and the data view (`d3d7af60-4c81-11e8-b3d7-01146121b73d`). value: @@ -1903,31 +2007,23 @@ components: value: data_view_id: ff959d40-b880-11e8-a6d9-e546fe2bba5f force: true - parameters: - kbn_xsrf: - schema: - type: string - in: header - name: kbn-xsrf - description: Cross-site request forgery protection - required: true - view_id: - in: path - name: viewId - description: An identifier for the data view. - required: true - schema: - type: string - example: ff959d40-b880-11e8-a6d9-e546fe2bba5f - field_name: - in: path - name: fieldName - description: The name of the runtime field. - required: true - schema: - type: string - example: hour_of_day schemas: + 400_response: + title: Bad request + type: object + required: + - statusCode + - error + - message + properties: + statusCode: + type: number + example: 400 + error: + type: string + example: Bad Request + message: + type: string allownoindex: type: boolean description: Allows the data view saved object to exist before the data is available. @@ -2042,22 +2138,6 @@ components: version: type: string example: WzQ2LDJd - 400_response: - title: Bad request - type: object - required: - - statusCode - - error - - message - properties: - statusCode: - type: number - example: 400 - error: - type: string - example: Bad Request - message: - type: string 404_response: type: object properties: @@ -2109,10 +2189,27 @@ components: type: boolean description: Reloads the data view fields after the data view is updated. default: false - create_runtime_field_response: - summary: The API returns created runtime field object array and updated data view object. - value: - data_view: - ...: null - fields: - - ... + parameters: + kbn_xsrf: + schema: + type: string + in: header + name: kbn-xsrf + description: Cross-site request forgery protection + required: true + view_id: + in: path + name: viewId + description: An identifier for the data view. + required: true + schema: + type: string + example: ff959d40-b880-11e8-a6d9-e546fe2bba5f + field_name: + in: path + name: fieldName + description: The name of the runtime field. + required: true + schema: + type: string + example: hour_of_day diff --git a/src/plugins/data_views/docs/openapi/components/examples/create_runtime_field_response.yaml b/src/plugins/data_views/docs/openapi/components/examples/create_runtime_field_response.yaml index ef23d12a835dd..281aeef90aa54 100644 --- a/src/plugins/data_views/docs/openapi/components/examples/create_runtime_field_response.yaml +++ b/src/plugins/data_views/docs/openapi/components/examples/create_runtime_field_response.yaml @@ -1,6 +1,6 @@ summary: The API returns created runtime field object array and updated data view object. value: - { + { "data_view": {...}, "fields": [...] - } \ No newline at end of file + } \ No newline at end of file diff --git a/src/plugins/data_views/docs/openapi/components/examples/update_field_metadata_request.yaml b/src/plugins/data_views/docs/openapi/components/examples/update_field_metadata_request.yaml new file mode 100644 index 0000000000000..ffa1eba13150f --- /dev/null +++ b/src/plugins/data_views/docs/openapi/components/examples/update_field_metadata_request.yaml @@ -0,0 +1,9 @@ +summary: Set popularity count for field foo. +value: + { + "fields": { + "foo": { + "count": 123 + } + } +} \ No newline at end of file diff --git a/src/plugins/data_views/docs/openapi/entrypoint.yaml b/src/plugins/data_views/docs/openapi/entrypoint.yaml index 3a45da60e6f92..15a9a0f20dd3f 100644 --- a/src/plugins/data_views/docs/openapi/entrypoint.yaml +++ b/src/plugins/data_views/docs/openapi/entrypoint.yaml @@ -22,8 +22,8 @@ paths: $ref: 'paths/api@data_views@data_view.yaml' '/api/data_views/data_view/{viewId}': $ref: 'paths/api@data_views@data_view@{viewid}.yaml' -# '/api/data_views/data_view/{viewId}/fields': -# $ref: 'paths/api@data_views@data_view@{viewid}@fields.yaml' + '/api/data_views/data_view/{viewId}/fields': + $ref: 'paths/api@data_views@data_view@{viewid}@fields.yaml' '/api/data_views/data_view/{viewId}/runtime_field': $ref: 'paths/api@data_views@data_view@{viewid}@runtime_field.yaml' '/api/data_views/data_view/{viewId}/runtime_field/{fieldName}': diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views.yaml index 9a3278f5ecbac..9ff2b230726aa 100644 --- a/src/plugins/data_views/docs/openapi/paths/api@data_views.yaml +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views.yaml @@ -33,5 +33,11 @@ get: examples: getAllDataViewsResponse: $ref: '../components/examples/get_data_views_response.yaml' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' servers: - url: https://localhost:5601 diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@fields.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@fields.yaml new file mode 100644 index 0000000000000..daca62afaac3a --- /dev/null +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@fields.yaml @@ -0,0 +1,46 @@ +post: + summary: Update fields presentation metadata such as count, customLabel and format. + operationId: updateFieldsMetadata + description: > + This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value. + tags: + - data views + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/view_id.yaml' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - fields + properties: + fields: + description: The field object. + type: object + examples: + updateFieldsMetadataRequest: + $ref: '../components/examples/update_field_metadata_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + properties: + acknowledged: + type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' + servers: + - url: https://localhost:5601 + +servers: + - url: https://localhost:5601 \ No newline at end of file diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml index 058c9aad774be..5b4c97e331208 100644 --- a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml @@ -7,49 +7,63 @@ post: - data views parameters: - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/view_id.yaml' requestBody: required: true content: application/json: schema: type: object + required: + - name + - runtimeField properties: - data_view_id: - description: The ID of the data view. + name: type: string - required: true - space_id: - description: An identifier for the space. If space_id is not provided in the URL, the default space is used. - type: string - required: false + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. examples: createRuntimeFieldRequest: $ref: '../components/examples/create_runtime_field_request.yaml' put: summary: Create or update an existing runtime field. - operationId: updateRuntimeField + operationId: createUpdateRuntimeField description: > This 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. tags: - data views parameters: - $ref: '../components/headers/kbn_xsrf.yaml' + - name: viewId + in: path + description: | + The ID of the data view fields you want to update. + required: true + schema: + type: string requestBody: required: true content: application/json: schema: type: object + required: + - name + - runtimeField properties: - data_view_id: - description: The ID of the data view. - type: string - required: true - space_id: - description: An identifier for the space. If space_id is not provided in the URL, the default space is used. + name: type: string - required: false + description: | + The name for a runtime field. + runtimeField: + type: object + description: | + The runtime field definition object. examples: updateRuntimeFieldRequest: $ref: '../components/examples/create_runtime_field_request.yaml' @@ -59,7 +73,15 @@ put: content: application/json: schema: - $ref: '../components/examples/create_runtime_field_response.yaml' + type: object + properties: + data_view: + type: object + fields: + type: array + examples: + createRuntimeFieldResponse: + $ref: '../components/examples/create_runtime_field_response.yaml' '400': description: Bad request content: diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml index 55f1e14dafb8a..f2da3921891d4 100644 --- a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field@{fieldname}.yaml @@ -68,13 +68,18 @@ post: application/json: schema: type: object + required: + - runtimeField properties: - data_view: + runtimeField: type: object - fields: - type: array - items: - type: object + description: | + The runtime field definition object. + + You can update following fields: + + - `type` + - `script` examples: updateRuntimeFieldRequest: $ref: '../components/examples/update_runtime_field_request.yaml' diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@default.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@default.yaml index cf1b3151380a9..8d7c92e164162 100644 --- a/src/plugins/data_views/docs/openapi/paths/api@data_views@default.yaml +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@default.yaml @@ -18,7 +18,12 @@ get: examples: getDefaultDataViewResponse: $ref: '../components/examples/get_default_data_view_response.yaml' - + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' post: summary: Sets the default data view identifier. operationId: setDefaultDatailView @@ -60,6 +65,12 @@ post: properties: acknowledged: type: boolean + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../components/schemas/400_response.yaml' servers: - url: https://localhost:5601 diff --git a/src/plugins/data_views/public/data_views_service_public.ts b/src/plugins/data_views/public/data_views_service_public.ts index 30625b1b59da5..73f4fb6987fa0 100644 --- a/src/plugins/data_views/public/data_views_service_public.ts +++ b/src/plugins/data_views/public/data_views_service_public.ts @@ -29,6 +29,7 @@ export interface DataViewsServicePublicDeps extends DataViewsServiceDeps { showAllIndices?: boolean; isRollupIndex: (indexName: string) => boolean; }) => Promise; + scriptedFieldsEnabled: boolean; } /** @@ -44,6 +45,7 @@ export class DataViewsServicePublic extends DataViewsService { isRollupIndex: (indexName: string) => boolean; }) => Promise; public hasData: HasDataService; + public readonly scriptedFieldsEnabled: boolean; /** * Constructor @@ -55,5 +57,6 @@ export class DataViewsServicePublic extends DataViewsService { this.getCanSaveSync = deps.getCanSaveSync; this.hasData = deps.hasData; this.getIndices = deps.getIndices; + this.scriptedFieldsEnabled = deps.scriptedFieldsEnabled; } } diff --git a/src/plugins/data_views/public/index.ts b/src/plugins/data_views/public/index.ts index 777e386189d62..f690552b5a147 100644 --- a/src/plugins/data_views/public/index.ts +++ b/src/plugins/data_views/public/index.ts @@ -6,6 +6,8 @@ * Side Public License, v 1. */ +import { PluginInitializerContext } from '@kbn/core/public'; + export { ILLEGAL_CHARACTERS_KEY, CONTAINS_SPACES_KEY, @@ -55,8 +57,8 @@ export { UiSettingsPublicToCommon } from './ui_settings_wrapper'; import { DataViewsPublicPlugin } from './plugin'; -export function plugin() { - return new DataViewsPublicPlugin(); +export function plugin(initializerContext: PluginInitializerContext) { + return new DataViewsPublicPlugin(initializerContext); } export type { diff --git a/src/plugins/data_views/public/plugin.ts b/src/plugins/data_views/public/plugin.ts index 119d785139c90..98558c803da10 100644 --- a/src/plugins/data_views/public/plugin.ts +++ b/src/plugins/data_views/public/plugin.ts @@ -6,9 +6,10 @@ * Side Public License, v 1. */ -import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; +import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { getIndexPatternLoad } from './expressions'; +import type { ClientConfigType } from '../common/types'; import { DataViewsPublicPluginSetup, DataViewsPublicPluginStart, @@ -40,6 +41,8 @@ export class DataViewsPublicPlugin { private readonly hasData = new HasData(); + constructor(private readonly initializerContext: PluginInitializerContext) {} + public setup( core: CoreSetup, { expressions, contentManagement }: DataViewsPublicSetupDependencies @@ -74,6 +77,8 @@ export class DataViewsPublicPlugin 10000 ); + const config = this.initializerContext.config.get(); + return new DataViewsServicePublic({ hasData: this.hasData.start(core), uiSettings: new UiSettingsPublicToCommon(uiSettings), @@ -91,6 +96,7 @@ export class DataViewsPublicPlugin getCanSaveAdvancedSettings: () => Promise.resolve(application.capabilities.advancedSettings.save === true), getIndices: (props) => getIndices({ ...props, http: core.http }), + scriptedFieldsEnabled: config.scriptedFieldsEnabled === false ? false : true, // accounting for null value }); } diff --git a/src/plugins/data_views/public/types.ts b/src/plugins/data_views/public/types.ts index c30aebe9243e0..fde0828748f93 100644 --- a/src/plugins/data_views/public/types.ts +++ b/src/plugins/data_views/public/types.ts @@ -120,6 +120,7 @@ export interface DataViewsServicePublic extends DataViewsServicePublicMethods { showAllIndices?: boolean; isRollupIndex: (indexName: string) => boolean; }) => Promise; + scriptedFieldsEnabled: boolean; } export type DataViewsContract = DataViewsServicePublic; diff --git a/src/plugins/data_views/server/data_views_service_factory.ts b/src/plugins/data_views/server/data_views_service_factory.ts index ac27ad0bc8093..e5324b2eb02d2 100644 --- a/src/plugins/data_views/server/data_views_service_factory.ts +++ b/src/plugins/data_views/server/data_views_service_factory.ts @@ -25,6 +25,7 @@ interface DataViewsServiceFactoryDeps { uiSettings: UiSettingsServiceStart; fieldFormats: FieldFormatsStart; capabilities: CoreStart['capabilities']; + scriptedFieldsEnabled: boolean; rollupsEnabled: boolean; } @@ -70,5 +71,6 @@ export const dataViewsServiceFactory = (deps: DataViewsServiceFactoryDeps) => : request ? (await capabilities.resolveCapabilities(request)).advancedSettings.save === true : false, + scriptedFieldsEnabled: deps.scriptedFieldsEnabled, }); }; diff --git a/src/plugins/data_views/server/index.ts b/src/plugins/data_views/server/index.ts index 33e93df3be894..a489feabbf935 100644 --- a/src/plugins/data_views/server/index.ts +++ b/src/plugins/data_views/server/index.ts @@ -6,6 +6,8 @@ * Side Public License, v 1. */ +import { schema, TypeOf } from '@kbn/config-schema'; +import type { PluginConfigDescriptor } from '@kbn/core/server'; export { getFieldByName, findIndexPatternById } from './utils'; export type { FieldDescriptor, RollupIndexCapability } from './fetcher'; export { IndexPatternsFetcher, getCapabilitiesForRollupIndices } from './fetcher'; @@ -36,6 +38,24 @@ export type { }; export { DataViewsServerPlugin as Plugin }; +const configSchema = schema.object({ + scriptedFieldsEnabled: schema.conditional( + schema.contextRef('serverless'), + true, + schema.boolean({ defaultValue: false }), + schema.never() + ), +}); + +type ConfigType = TypeOf; + +export const config: PluginConfigDescriptor = { + schema: configSchema, + exposeToBrowser: { + scriptedFieldsEnabled: true, + }, +}; + export { SERVICE_PATH, SERVICE_PATH_LEGACY, diff --git a/src/plugins/data_views/server/mocks.ts b/src/plugins/data_views/server/mocks.ts index 82595f7dc51a1..1e142d2e1650b 100644 --- a/src/plugins/data_views/server/mocks.ts +++ b/src/plugins/data_views/server/mocks.ts @@ -12,6 +12,7 @@ export function createIndexPatternsStartMock() { const dataViewsServiceFactory = jest.fn().mockResolvedValue({ get: jest.fn() }); return { dataViewsServiceFactory, + getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), }; } diff --git a/src/plugins/data_views/server/plugin.ts b/src/plugins/data_views/server/plugin.ts index c96de2e4294f0..2be269b1a7636 100644 --- a/src/plugins/data_views/server/plugin.ts +++ b/src/plugins/data_views/server/plugin.ts @@ -15,6 +15,7 @@ import { getIndexPatternLoad } from './expressions'; import { registerIndexPatternsUsageCollector } from './register_index_pattern_usage_collection'; import { createScriptedFieldsDeprecationsConfig } from './deprecations'; import { DATA_VIEW_SAVED_OBJECT_TYPE, LATEST_VERSION } from '../common'; +import type { ClientConfigType } from '../common/types'; import { DataViewsServerPluginSetup, DataViewsServerPluginStart, @@ -35,7 +36,7 @@ export class DataViewsServerPlugin private readonly logger: Logger; private rollupsEnabled: boolean = false; - constructor(initializerContext: PluginInitializerContext) { + constructor(private readonly initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get('dataView'); } @@ -75,16 +76,21 @@ export class DataViewsServerPlugin { uiSettings, capabilities }: CoreStart, { fieldFormats }: DataViewsServerPluginStartDependencies ) { + const config = this.initializerContext.config.get(); + const scriptedFieldsEnabled = config.scriptedFieldsEnabled === false ? false : true; // accounting for null value + const serviceFactory = dataViewsServiceFactory({ logger: this.logger.get('indexPatterns'), uiSettings, fieldFormats, capabilities, + scriptedFieldsEnabled, rollupsEnabled: this.rollupsEnabled, }); return { dataViewsServiceFactory: serviceFactory, + getScriptedFieldsEnabled: () => scriptedFieldsEnabled, }; } diff --git a/src/plugins/data_views/server/types.ts b/src/plugins/data_views/server/types.ts index d595f6e04b275..6bf438dc634bd 100644 --- a/src/plugins/data_views/server/types.ts +++ b/src/plugins/data_views/server/types.ts @@ -48,6 +48,10 @@ export interface DataViewsServerPluginStart { * Returns a DataViews service instance */ dataViewsServiceFactory: ServiceFactory; + /** + * + */ + getScriptedFieldsEnabled: () => boolean; } /** 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__/grid_context.ts b/src/plugins/discover/public/__mocks__/grid_context.ts deleted file mode 100644 index 8949945c2b0d8..0000000000000 --- a/src/plugins/discover/public/__mocks__/grid_context.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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/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 { buildDataTableRecord } from '@kbn/discover-utils'; -import type { EsHitRecord } from '@kbn/discover-utils/types'; - -const buildGridContext = (dataView: DataView, rows: EsHitRecord[]): GridContext => { - const usedRows = rows.map((row) => { - return buildDataTableRecord(row, dataView); - }); - - return { - expanded: undefined, - setExpanded: jest.fn(), - rows: usedRows, - onFilter: jest.fn(), - dataView, - isDarkMode: false, - selectedDocs: [], - setSelectedDocs: jest.fn(), - valueToStringConverter: (rowIndex, columnId, options) => - convertValueToString({ - rowIndex, - columnId, - fieldFormats: discoverServiceMock.fieldFormats, - rows: usedRows, - dataView, - options, - }), - }; -}; - -export const discoverGridContextMock = buildGridContext(dataViewMock, esHitsMock); - -export const discoverGridContextComplexMock = buildGridContext(dataViewComplexMock, esHitsComplex); 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/doc/types.ts b/src/plugins/discover/public/application/doc/types.ts deleted file mode 100644 index dd82e86cdb4b6..0000000000000 --- a/src/plugins/discover/public/application/doc/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export enum ElasticRequestState { - Loading, - NotFound, - Found, - Error, - NotFoundDataView, -} 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_sql.ts deleted file mode 100644 index 73c716e8f9351..0000000000000 --- a/src/plugins/discover/public/application/main/utils/fetch_sql.ts +++ /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 { pluck } from 'rxjs/operators'; -import { lastValueFrom } from 'rxjs'; -import { Query, AggregateQuery, Filter } from '@kbn/es-query'; -import type { Adapters } from '@kbn/inspector-plugin/common'; -import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; -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'; - -interface SQLErrorResponse { - error: { - message: string; - }; - type: 'error'; -} - -export function fetchSql( - query: Query | AggregateQuery, - dataView: DataView, - data: DataPublicPluginStart, - expressions: ExpressionsStart, - inspectorAdapters: Adapters, - filters?: Filter[], - inputQuery?: Query -): Promise { - const timeRange = data.query.timefilter.timefilter.getTime(); - return textBasedQueryStateToAstWithValidation({ - filters, - query, - time: timeRange, - dataView, - inputQuery, - }) - .then((ast) => { - if (ast) { - const execution = expressions.run(ast, null, { - inspectorAdapters, - }); - let finalData: DataTableRecord[] = []; - let textBasedQueryColumns: Datatable['columns'] | undefined; - let error: string | undefined; - execution.pipe(pluck('result')).subscribe((resp) => { - const response = resp as Datatable | SQLErrorResponse; - if (response.type === 'error') { - error = response.error.message; - } else { - const table = response as Datatable; - const rows = table?.rows ?? []; - textBasedQueryColumns = table?.columns ?? undefined; - finalData = rows.map( - (row: Record, idx: number) => - ({ - id: String(idx), - raw: row, - flattened: row, - } as unknown as DataTableRecord) - ); - } - }); - return lastValueFrom(execution).then(() => { - if (error) { - throw new Error(error); - } else { - return { - records: finalData || [], - textBasedQueryColumns, - }; - } - }); - } - return { - records: [] as DataTableRecord[], - textBasedQueryColumns: [], - }; - }) - .catch((err) => { - throw new Error(err.message); - }); -} diff --git a/src/plugins/discover/public/application/main/utils/fetch_text_based.ts b/src/plugins/discover/public/application/main/utils/fetch_text_based.ts new file mode 100644 index 0000000000000..6a164bfd8a5f8 --- /dev/null +++ b/src/plugins/discover/public/application/main/utils/fetch_text_based.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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, Filter } from '@kbn/es-query'; +import type { Adapters } from '@kbn/inspector-plugin/common'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; +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 type { RecordsFetchResponse } from '../../types'; + +interface TextBasedErrorResponse { + error: { + message: string; + }; + type: 'error'; +} + +export function fetchTextBased( + query: Query | AggregateQuery, + dataView: DataView, + data: DataPublicPluginStart, + expressions: ExpressionsStart, + inspectorAdapters: Adapters, + filters?: Filter[], + inputQuery?: Query +): Promise { + const timeRange = data.query.timefilter.timefilter.getTime(); + return textBasedQueryStateToAstWithValidation({ + filters, + query, + time: timeRange, + dataView, + inputQuery, + }) + .then((ast) => { + if (ast) { + const execution = expressions.run(ast, null, { + inspectorAdapters, + }); + 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 | 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) => + ({ + id: String(idx), + raw: row, + flattened: row, + } as unknown as DataTableRecord) + ); + } + }); + return lastValueFrom(execution).then(() => { + if (error) { + throw new Error(error); + } else { + return { + records: finalData || [], + textBasedQueryColumns, + textBasedHeaderWarning, + }; + } + }); + } + return { + records: [] as DataTableRecord[], + textBasedQueryColumns: [], + textBasedHeaderWarning: undefined, + }; + }) + .catch((err) => { + throw new Error(err.message); + }); +} 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/constants.ts b/src/plugins/discover/public/components/discover_grid/constants.ts deleted file mode 100644 index 8f7c40e33b957..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/constants.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { EuiDataGridStyle } from '@elastic/eui'; - -// data types -export const kibanaJSON = 'kibana-json'; -export const GRID_STYLE = { - border: 'all', - fontSize: 's', - cellPadding: 's', - 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/components/discover_grid/discover_grid.scss b/src/plugins/discover/public/components/discover_grid/discover_grid.scss deleted file mode 100644 index 0e870d366b609..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid.scss +++ /dev/null @@ -1,138 +0,0 @@ -.dscDiscoverGrid { - width: 100%; - max-width: 100%; - height: 100%; - overflow: hidden; - border-radius: $euiBorderRadius; - - .euiDataGrid__controls { - border: none; - border-bottom: $euiBorderThin; - } - - .euiDataGridRowCell.euiDataGridRowCell--firstColumn { - border-left: none; - padding: 0; - } - - .euiDataGridRowCell.euiDataGridRowCell--lastColumn { - border-right: none; - } - - .dscDiscoverGrid__table .euiDataGridRowCell:first-of-type, - .dscDiscoverGrid__table .euiDataGrid--headerShade.euiDataGrid--bordersAll .euiDataGridHeaderCell:first-of-type { - border-left: none; - border-right: none; - } - - .euiDataGridRowCell:last-of-type, - .euiDataGridHeaderCell:last-of-type { - border-right: none; - } -} - -.dscDiscoverGrid__cellValue { - font-family: $euiCodeFontFamily; -} - -.dscDiscoverGrid__cellPopover { - // Fixes https://github.com/elastic/kibana/issues/145216 in Chrome - .lines-content.monaco-editor-background { - overflow: unset !important; - contain: unset !important; - } -} - -.dscDiscoverGrid__cellPopoverValue { - font-family: $euiCodeFontFamily; - font-size: $euiFontSizeS; -} - -.euiDataGridRowCell__definedHeight { - white-space: pre-wrap; -} - -.dscDiscoverGrid__inner { - display: flex; - flex-direction: column; - flex-wrap: nowrap; - height: 100%; -} - -.dscDiscoverGrid__table { - flex-grow: 1; - flex-shrink: 1; - min-height: 0; -} - -.dscTable__flyoutHeader { - white-space: nowrap; -} - -.dscTable__flyoutDocumentNavigation { - justify-content: flex-end; -} - -// We only truncate if the cell is not a control column. -.euiDataGridHeader { - - .euiDataGridHeaderCell__content { - @include euiTextTruncate; - overflow: hidden; - white-space: pre-wrap; - flex-grow: 1; - } - - .euiDataGridHeaderCell__popover { - flex-grow: 0; - flex-basis: auto; - width: auto; - padding-left: $euiSizeXS; - } -} - -.euiDataGridRowCell--numeric { - text-align: right; -} - -.euiDataGrid__loading, -.euiDataGrid__noResults { - display: flex; - flex-direction: column; - justify-content: center; - flex: 1 0 100%; - text-align: center; - height: 100%; - width: 100%; -} - -.dscFormatSource { - @include euiTextTruncate; -} - -.dscDiscoverGrid__descriptionListDescription { - word-break: break-all; - white-space: normal; - - // Special handling for images coming from the image field formatter - img { - // Align the images vertically centered with the text - vertical-align: middle; - // Set the maximum height to the line-height. The used function is the same - // function used to calculate the line-height for the EuiDescriptionList Description. - // !important is required to overwrite the max-height on the element from the field formatter - max-height: lineHeightFromBaseline(2) !important; - // An arbitrary amount of width we don't want to go over, to not have very wide images. - // For most width-height-ratios that will never be hit, because we'd usually limit - // it by the way smaller height. But images with very large width and very small height - // might be limited by that. - max-width: ($euiSizeXXL * 12.5) !important; - } -} - -@include euiBreakpoint('xs', 's', 'm') { - // EUI issue to hide 'of' text https://github.com/elastic/eui/issues/4654 - .dscTable__flyoutDocumentNavigation .euiPagination__compressedText { - display: none; - } -} diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid.test.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid.test.tsx deleted file mode 100644 index 153126b4d471c..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid.test.tsx +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { ReactWrapper } from 'enzyme'; -import { EuiCopy } from '@elastic/eui'; -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 { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { discoverServiceMock } from '../../__mocks__/services'; -import { buildDataTableRecord, getDocId } from '@kbn/discover-utils'; -import type { EsHitRecord } from '@kbn/discover-utils/types'; - -const mockUseDataGridColumnsCellActions = jest.fn((prop: unknown) => []); -jest.mock('@kbn/cell-actions', () => ({ - ...jest.requireActual('@kbn/cell-actions'), - useDataGridColumnsCellActions: (prop: unknown) => mockUseDataGridColumnsCellActions(prop), -})); - -export const dataViewMock = buildDataViewMock({ - name: 'the-data-view', - fields: deepMockedFields, - timeFieldName: '@timestamp', -}); - -function getProps() { - const services = discoverServiceMock; - services.dataViewFieldEditor.userPermissions.editIndexPattern = jest.fn().mockReturnValue(true); - - return { - ariaLabelledBy: '', - columns: [], - 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(), - rows: esHitsMock.map((hit) => buildDataTableRecord(hit, dataViewMock)), - sampleSize: 30, - searchDescription: '', - searchTitle: '', - setExpandedDoc: jest.fn(), - settings: {}, - showTimeCol: true, - sort: [], - useNewFieldsApi: true, - services, - }; -} - -async function getComponent(props: DiscoverGridProps = getProps()) { - const Proxy = (innerProps: DiscoverGridProps) => ( - - - - ); - - const component = mountWithIntl(); - await act(async () => { - // needed by cell actions to complete async loading - component.update(); - }); - return component; -} - -function getSelectedDocNr(component: ReactWrapper) { - const gridSelectionBtn = findTestSubject(component, 'dscGridSelectionBtn'); - if (!gridSelectionBtn.length) { - return 0; - } - const selectedNr = gridSelectionBtn.getDOMNode().getAttribute('data-selected-documents'); - return Number(selectedNr); -} - -function getDisplayedDocNr(component: ReactWrapper) { - const gridSelectionBtn = findTestSubject(component, 'discoverDocTable'); - if (!gridSelectionBtn.length) { - return 0; - } - const selectedNr = gridSelectionBtn.getDOMNode().getAttribute('data-document-number'); - return Number(selectedNr); -} - -async function toggleDocSelection( - component: ReactWrapper, - document: EsHitRecord -) { - act(() => { - const docId = getDocId(document); - findTestSubject(component, `dscGridSelectDoc-${docId}`).simulate('change'); - }); - component.update(); -} - -describe('DiscoverGrid', () => { - afterEach(async () => { - jest.clearAllMocks(); - }); - - describe('Document selection', () => { - let component: ReactWrapper; - beforeEach(async () => { - component = await getComponent(); - }); - - test('no documents are selected initially', async () => { - expect(getSelectedDocNr(component)).toBe(0); - expect(getDisplayedDocNr(component)).toBe(5); - }); - - test('Allows selection/deselection of multiple documents', async () => { - await toggleDocSelection(component, esHitsMock[0]); - expect(getSelectedDocNr(component)).toBe(1); - await toggleDocSelection(component, esHitsMock[1]); - expect(getSelectedDocNr(component)).toBe(2); - await toggleDocSelection(component, esHitsMock[1]); - expect(getSelectedDocNr(component)).toBe(1); - }); - - test('deselection of all selected documents', async () => { - await toggleDocSelection(component, esHitsMock[0]); - await toggleDocSelection(component, esHitsMock[1]); - expect(getSelectedDocNr(component)).toBe(2); - findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); - findTestSubject(component, 'dscGridClearSelectedDocuments').simulate('click'); - expect(getSelectedDocNr(component)).toBe(0); - }); - - test('showing only selected documents and undo selection', async () => { - await toggleDocSelection(component, esHitsMock[0]); - await toggleDocSelection(component, esHitsMock[1]); - expect(getSelectedDocNr(component)).toBe(2); - findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); - findTestSubject(component, 'dscGridShowSelectedDocuments').simulate('click'); - expect(getDisplayedDocNr(component)).toBe(2); - findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); - component.update(); - findTestSubject(component, 'dscGridShowAllDocuments').simulate('click'); - expect(getDisplayedDocNr(component)).toBe(5); - }); - - test('showing selected documents, underlying data changes, all documents are displayed, selection is gone', async () => { - await toggleDocSelection(component, esHitsMock[0]); - await toggleDocSelection(component, esHitsMock[1]); - expect(getSelectedDocNr(component)).toBe(2); - findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); - findTestSubject(component, 'dscGridShowSelectedDocuments').simulate('click'); - expect(getDisplayedDocNr(component)).toBe(2); - component.setProps({ - rows: [ - { - _index: 'i', - _id: '6', - _score: 1, - _source: { - date: '2020-20-02T12:12:12.128', - name: 'test6', - extension: 'doc', - bytes: 50, - }, - }, - ].map((row) => buildDataTableRecord(row, dataViewMock)), - }); - expect(getDisplayedDocNr(component)).toBe(1); - expect(getSelectedDocNr(component)).toBe(0); - }); - - test('showing only selected documents and remove filter deselecting each doc manually', async () => { - await toggleDocSelection(component, esHitsMock[0]); - findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); - findTestSubject(component, 'dscGridShowSelectedDocuments').simulate('click'); - expect(getDisplayedDocNr(component)).toBe(1); - await toggleDocSelection(component, esHitsMock[0]); - expect(getDisplayedDocNr(component)).toBe(5); - await toggleDocSelection(component, esHitsMock[0]); - expect(getDisplayedDocNr(component)).toBe(5); - }); - - test('copying selected documents to clipboard', async () => { - await toggleDocSelection(component, esHitsMock[0]); - findTestSubject(component, 'dscGridSelectionBtn').simulate('click'); - expect(component.find(EuiCopy).prop('textToCopy')).toMatchInlineSnapshot( - `"[{\\"_index\\":\\"i\\",\\"_id\\":\\"1\\",\\"_score\\":1,\\"_type\\":\\"_doc\\",\\"_source\\":{\\"date\\":\\"2020-20-01T12:12:12.123\\",\\"message\\":\\"test1\\",\\"bytes\\":20}}]"` - ); - }); - }); - - describe('edit field button', () => { - it('should render the edit field button if onFieldEdited is provided', async () => { - const component = await getComponent({ - ...getProps(), - columns: ['message'], - onFieldEdited: jest.fn(), - }); - expect(findTestSubject(component, 'dataGridHeaderCellActionGroup-message').exists()).toBe( - false - ); - findTestSubject(component, 'dataGridHeaderCell-message').find('button').simulate('click'); - expect(findTestSubject(component, 'dataGridHeaderCellActionGroup-message').exists()).toBe( - true - ); - expect(findTestSubject(component, 'gridEditFieldButton').exists()).toBe(true); - }); - - it('should not render the edit field button if onFieldEdited is not provided', async () => { - const component = await getComponent({ - ...getProps(), - columns: ['message'], - }); - expect(findTestSubject(component, 'dataGridHeaderCellActionGroup-message').exists()).toBe( - false - ); - findTestSubject(component, 'dataGridHeaderCell-message').find('button').simulate('click'); - expect(findTestSubject(component, 'dataGridHeaderCellActionGroup-message').exists()).toBe( - true - ); - expect(findTestSubject(component, 'gridEditFieldButton').exists()).toBe(false); - }); - }); - - describe('cellActionsTriggerId', () => { - it('should call useDataGridColumnsCellActions with empty params when no cellActionsTriggerId is provided', async () => { - await getComponent({ - ...getProps(), - columns: ['message'], - onFieldEdited: jest.fn(), - }); - expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith( - expect.objectContaining({ - triggerId: undefined, - getCellValue: expect.any(Function), - fields: undefined, - }) - ); - }); - - it('should call useDataGridColumnsCellActions properly when cellActionsTriggerId defined', async () => { - await getComponent({ - ...getProps(), - columns: ['message'], - onFieldEdited: jest.fn(), - cellActionsTriggerId: 'test', - }); - expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith( - expect.objectContaining({ - triggerId: 'test', - getCellValue: expect.any(Function), - fields: [ - dataViewMock.getFieldByName('@timestamp')?.toSpec(), - dataViewMock.getFieldByName('message')?.toSpec(), - ], - }) - ); - }); - }); - - describe('sorting', () => { - it('should enable in memory sorting with plain records', async () => { - const component = await getComponent({ - ...getProps(), - columns: ['message'], - isPlainRecord: true, - }); - - expect( - ( - findTestSubject(component, 'docTable') - .find('EuiDataGridInMemoryRenderer') - .first() - .props() as Record - ).inMemory - ).toMatchInlineSnapshot(` - Object { - "level": "sorting", - } - `); - }); - }); -}); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid.tsx deleted file mode 100644 index 414b8986e5cbc..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx +++ /dev/null @@ -1,753 +0,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, { useCallback, useMemo, useState, useRef, useEffect } from 'react'; -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 { - EuiDataGridSorting, - EuiDataGrid, - EuiScreenReaderOnly, - EuiSpacer, - EuiText, - htmlIdGenerator, - EuiLoadingSpinner, - EuiIcon, - EuiDataGridRefProps, - EuiDataGridInMemory, -} 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 { DataTableRecord } from '@kbn/discover-utils/types'; -import { getShouldShowFieldHandler } from '@kbn/discover-utils'; -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'; - -export enum DataLoadingState { - loading = 'loading', - loadingMore = 'loadingMore', - loaded = 'loaded', -} - -const themeDefault = { darkMode: false }; - -interface SortObj { - id: string; - direction: string; -} - -export interface DiscoverGridProps { - /** - * Determines which element labels the grid for ARIA - */ - ariaLabelledBy: string; - /** - * Optional class name to apply - */ - className?: string; - /** - * Determines which columns are displayed - */ - columns: string[]; - /** - * If set, the given document is displayed in a flyout - */ - expandedDoc?: DataTableRecord; - /** - * The used data view - */ - dataView: DataView; - /** - * 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 - */ - onResize?: (colSettings: { columnId: string; width: number }) => void; - /** - * Function to set all columns - */ - onSetColumns: (columns: string[], hideTimeColumn: boolean) => void; - /** - * function to change sorting of the documents, skipped when isSortEnabled is set to false - */ - onSort?: (sort: string[][]) => void; - /** - * Array of documents provided by Elasticsearch - */ - rows?: DataTableRecord[]; - /** - * The max size of the documents returned by Elasticsearch - */ - sampleSize: number; - /** - * Function to set the expanded document, which is displayed in a flyout - */ - setExpandedDoc?: (doc?: DataTableRecord) => void; - /** - * Grid display settings persisted in Elasticsearch (e.g. column width) - */ - settings?: DiscoverGridSettings; - /** - * Saved search description - */ - searchDescription?: string; - /** - * Saved search title - */ - searchTitle?: string; - /** - * Determines whether the time columns should be displayed (legacy settings) - */ - showTimeCol: boolean; - /** - * Determines whether the full screen button should be displayed - */ - showFullScreenButton?: boolean; - /** - * Manage user sorting control - */ - isSortEnabled?: boolean; - /** - * Current sort setting - */ - sort: SortOrder[]; - /** - * How the data is fetched - */ - useNewFieldsApi: boolean; - /** - * Manage pagination control - */ - isPaginationEnabled?: boolean; - /** - * List of used control columns (available: 'openDetails', 'select') - */ - controlColumnIds?: string[]; - /** - * Row height from state - */ - rowHeightState?: number; - /** - * Update row height state - */ - onUpdateRowHeight?: (rowHeight: number) => void; - /** - * Is text base lang mode enabled - */ - isPlainRecord?: boolean; - /** - * Current state value for rowsPerPage - */ - rowsPerPageState?: number; - /** - * Update rows per page state - */ - onUpdateRowsPerPage?: (rowsPerPage: number) => void; - /** - * 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 - */ - cellActionsTriggerId?: string; - /** - * Service dependencies - */ - services: { - core: CoreStart; - fieldFormats: FieldFormatsStart; - addBasePath: HttpStart['basePath']['prepend']; - uiSettings: IUiSettingsClient; - dataViewFieldEditor: DataViewFieldEditorStart; - toastNotifications: ToastsStart; - }; - /** - * Number total hits from ES - */ - totalHits?: number; - /** - * To fetch more - */ - onFetchMoreRecords?: () => void; -} - -export const EuiDataGridMemoized = React.memo(EuiDataGrid); - -const CONTROL_COLUMN_IDS_DEFAULT = ['openDetails', 'select']; - -export const DiscoverGrid = ({ - ariaLabelledBy, - columns, - dataView, - loadingState, - expandedDoc, - onAddColumn, - filters, - query, - savedSearchId, - onFilter, - onRemoveColumn, - onResize, - onSetColumns, - onSort, - rows, - sampleSize, - searchDescription, - searchTitle, - setExpandedDoc, - settings, - showTimeCol, - showFullScreenButton = true, - sort, - useNewFieldsApi, - isSortEnabled = true, - isPaginationEnabled = true, - controlColumnIds = CONTROL_COLUMN_IDS_DEFAULT, - cellActionsTriggerId, - className, - rowHeightState, - onUpdateRowHeight, - isPlainRecord = false, - rowsPerPageState, - onUpdateRowsPerPage, - onFieldEdited, - DocumentView, - services, - totalHits, - onFetchMoreRecords, -}: DiscoverGridProps) => { - const { fieldFormats, toastNotifications, dataViewFieldEditor, uiSettings } = services; - const { darkMode } = useObservable(services.core.theme?.theme$ ?? of(themeDefault), themeDefault); - const dataGridRef = useRef(null); - const [selectedDocs, setSelectedDocs] = useState([]); - const [isFilterActive, setIsFilterActive] = useState(false); - const displayedColumns = getDisplayedColumns(columns, dataView); - const defaultColumns = displayedColumns.includes('_source'); - const usedSelectedDocs = useMemo(() => { - if (!selectedDocs.length || !rows?.length) { - return []; - } - 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)); - if (result.length === 0 && isFilterActive) { - setIsFilterActive(false); - } - return result; - }, [selectedDocs, rows, isFilterActive]); - - const displayedRows = useMemo(() => { - if (!rows) { - return []; - } - if (!isFilterActive || usedSelectedDocs.length === 0) { - return rows; - } - const rowsFiltered = rows.filter((row) => usedSelectedDocs.includes(row.id)); - if (!rowsFiltered.length) { - // in case the selected docs are no longer part of the sample of 500, show all docs - return rows; - } - return rowsFiltered; - }, [rows, usedSelectedDocs, isFilterActive]); - - const valueToStringConverter: ValueToStringConverter = useCallback( - (rowIndex, columnId, options) => { - return convertValueToString({ - rowIndex, - rows: displayedRows, - dataView, - columnId, - fieldFormats, - options, - }); - }, - [displayedRows, dataView, fieldFormats] - ); - - /** - * Pagination - */ - const defaultRowsPerPage = useMemo( - () => getDefaultRowsPerPage(services.uiSettings), - [services.uiSettings] - ); - const currentPageSize = - typeof rowsPerPageState === 'number' && rowsPerPageState > 0 - ? rowsPerPageState - : defaultRowsPerPage; - const [pagination, setPagination] = useState({ - pageIndex: 0, - pageSize: currentPageSize, - }); - const rowCount = useMemo(() => (displayedRows ? displayedRows.length : 0), [displayedRows]); - const pageCount = useMemo( - () => Math.ceil(rowCount / pagination.pageSize), - [rowCount, pagination] - ); - - const paginationObj = useMemo(() => { - const onChangeItemsPerPage = (pageSize: number) => { - onUpdateRowsPerPage?.(pageSize); - }; - - const onChangePage = (pageIndex: number) => - setPagination((paginationData) => ({ ...paginationData, pageIndex })); - - return isPaginationEnabled - ? { - onChangeItemsPerPage, - onChangePage, - pageIndex: pagination.pageIndex > pageCount - 1 ? 0 : pagination.pageIndex, - pageSize: pagination.pageSize, - pageSizeOptions: getRowsPerPageOptions(pagination.pageSize), - } - : undefined; - }, [pagination, pageCount, isPaginationEnabled, onUpdateRowsPerPage]); - - useEffect(() => { - setPagination((paginationData) => - paginationData.pageSize === currentPageSize - ? paginationData - : { ...paginationData, pageSize: currentPageSize } - ); - }, [currentPageSize, setPagination]); - - /** - * Sorting - */ - const sortingColumns = useMemo(() => sort.map(([id, direction]) => ({ id, direction })), [sort]); - - const [inmemorySortingColumns, setInmemorySortingColumns] = useState([]); - const onTableSort = useCallback( - (sortingColumnsData) => { - if (isSortEnabled) { - if (isPlainRecord) { - setInmemorySortingColumns(sortingColumnsData); - } else if (onSort) { - onSort(sortingColumnsData.map(({ id, direction }: SortObj) => [id, direction])); - } - } - }, - [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); - }, [dataView, showMultiFields]); - - /** - * Cell rendering - */ - const renderCellValue = useMemo( - () => - getRenderCellValueFn( - dataView, - displayedRows, - useNewFieldsApi, - shouldShowFieldHandler, - services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED), - () => dataGridRef.current?.closeCellPopover() - ), - [dataView, displayedRows, useNewFieldsApi, shouldShowFieldHandler, services.uiSettings] - ); - - /** - * Render variables - */ - const randomId = useMemo(() => htmlIdGenerator()(), []); - const closeFieldEditor = useRef<() => void | undefined>(); - - useEffect(() => { - return () => { - if (closeFieldEditor?.current) { - closeFieldEditor?.current(); - } - }; - }, []); - - const editField = useMemo( - () => - onFieldEdited - ? (fieldName: string) => { - closeFieldEditor.current = services.dataViewFieldEditor.openEditor({ - ctx: { - dataView, - }, - fieldName, - onSave: async () => { - await onFieldEdited(); - }, - }); - } - : undefined, - [dataView, onFieldEdited, services.dataViewFieldEditor] - ); - - const visibleColumns = useMemo( - () => getVisibleColumns(displayedColumns, dataView, showTimeCol) as string[], - [dataView, displayedColumns, showTimeCol] - ); - - const getCellValue = useCallback( - (fieldName, rowIndex) => - displayedRows[rowIndex % displayedRows.length].flattened[fieldName] as Serializable, - [displayedRows] - ); - - const cellActionsFields = useMemo( - () => - cellActionsTriggerId && !isPlainRecord - ? visibleColumns.map( - (columnName) => - dataView.getFieldByName(columnName)?.toSpec() ?? { - name: '', - type: '', - aggregatable: false, - searchable: false, - } - ) - : undefined, - [cellActionsTriggerId, isPlainRecord, visibleColumns, dataView] - ); - - const columnsCellActions = useDataGridColumnsCellActions({ - fields: cellActionsFields, - getCellValue, - triggerId: cellActionsTriggerId, - dataGridRef, - }); - - const euiGridColumns = useMemo( - () => - getEuiGridColumns({ - columns: visibleColumns, - columnsCellActions, - rowsCount: displayedRows.length, - settings, - dataView, - defaultColumns, - isSortEnabled, - isPlainRecord, - services: { - uiSettings, - toastNotifications, - }, - hasEditDataViewPermission: () => dataViewFieldEditor.userPermissions.editIndexPattern(), - valueToStringConverter, - onFilter, - editField, - }), - [ - onFilter, - visibleColumns, - columnsCellActions, - displayedRows, - dataView, - settings, - defaultColumns, - isSortEnabled, - isPlainRecord, - uiSettings, - toastNotifications, - dataViewFieldEditor, - valueToStringConverter, - editField, - ] - ); - - const hideTimeColumn = useMemo( - () => services.uiSettings.get(DOC_HIDE_TIME_COLUMN_SETTING, false), - [services.uiSettings] - ); - const schemaDetectors = useMemo(() => getSchemaDetectors(), []); - const columnsVisibility = useMemo( - () => ({ - visibleColumns, - setVisibleColumns: (newColumns: string[]) => { - onSetColumns(newColumns, hideTimeColumn); - }, - }), - [visibleColumns, hideTimeColumn, onSetColumns] - ); - const sorting = useMemo(() => { - if (isSortEnabled) { - return { - columns: isPlainRecord ? inmemorySortingColumns : sortingColumns, - onSort: onTableSort, - }; - } - return { columns: sortingColumns, onSort: () => {} }; - }, [isSortEnabled, sortingColumns, isPlainRecord, inmemorySortingColumns, onTableSort]); - - const canSetExpandedDoc = Boolean(setExpandedDoc && DocumentView); - - const lead = useMemo( - () => - getLeadControlColumns(canSetExpandedDoc).filter(({ id }) => controlColumnIds.includes(id)), - [controlColumnIds, canSetExpandedDoc] - ); - - const additionalControls = useMemo( - () => - usedSelectedDocs.length ? ( - - ) : null, - [usedSelectedDocs, isFilterActive, rows, setIsFilterActive] - ); - - const showDisplaySelector = useMemo( - () => - !!onUpdateRowHeight - ? { - allowDensity: false, - allowRowHeight: true, - } - : undefined, - [onUpdateRowHeight] - ); - - const inMemory = useMemo(() => { - return isPlainRecord ? ({ level: 'sorting' } as EuiDataGridInMemory) : undefined; - }, [isPlainRecord]); - - const toolbarVisibility = useMemo( - () => - defaultColumns - ? { - ...toolbarVisibilityDefaults, - showColumnSelector: false, - showSortSelector: isSortEnabled, - additionalControls, - showDisplaySelector, - showFullScreenSelector: showFullScreenButton, - } - : { - ...toolbarVisibilityDefaults, - showSortSelector: isSortEnabled, - additionalControls, - showDisplaySelector, - showFullScreenSelector: showFullScreenButton, - }, - [defaultColumns, isSortEnabled, additionalControls, showDisplaySelector, showFullScreenButton] - ); - - const rowHeightsOptions = useRowHeightsOptions({ - rowHeightState, - onUpdateRowHeight, - }); - - const isRenderComplete = loadingState !== DataLoadingState.loading; - - if (!rowCount && loadingState === DataLoadingState.loading) { - return ( -
    - - - - - -
    - ); - } - - if (!rowCount) { - return ( -
    - - - - - -
    - ); - } - - return ( - { - setSelectedDocs(newSelectedDocs); - if (isFilterActive && newSelectedDocs.length === 0) { - setIsFilterActive(false); - } - }, - valueToStringConverter, - }} - > - -
    - -
    - {loadingState !== DataLoadingState.loading && - isPaginationEnabled && ( // we hide the footer for Surrounding Documents page - - )} - {searchTitle && ( - -

    - {searchDescription ? ( - - ) : ( - - )} -

    -
    - )} - {setExpandedDoc && expandedDoc && DocumentView && ( - setExpandedDoc(undefined)} - setExpandedDoc={setExpandedDoc} - query={query} - /> - )} -
    -
    - ); -}; 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_cell_actions.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_cell_actions.tsx deleted file mode 100644 index 59cd130277f90..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_cell_actions.tsx +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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, { 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'; - -function onFilterCell( - context: GridContext, - rowIndex: EuiDataGridColumnCellActionProps['rowIndex'], - columnId: EuiDataGridColumnCellActionProps['columnId'], - mode: '+' | '-' -) { - const row = context.rows[rowIndex]; - const value = row.flattened[columnId]; - const field = context.dataView.fields.getByName(columnId); - - if (field && context.onFilter) { - context.onFilter(field, value, mode); - } -} - -export const FilterInBtn = ({ - Component, - rowIndex, - columnId, -}: EuiDataGridColumnCellActionProps) => { - const context = useContext(DiscoverGridContext); - const buttonTitle = i18n.translate('discover.grid.filterForAria', { - defaultMessage: 'Filter for this {value}', - values: { value: columnId }, - }); - - return ( - { - onFilterCell(context, rowIndex, columnId, '+'); - }} - iconType="plusInCircle" - aria-label={buttonTitle} - title={buttonTitle} - data-test-subj="filterForButton" - > - {i18n.translate('discover.grid.filterFor', { - defaultMessage: 'Filter for', - })} - - ); -}; - -export const FilterOutBtn = ({ - Component, - rowIndex, - columnId, -}: EuiDataGridColumnCellActionProps) => { - const context = useContext(DiscoverGridContext); - const buttonTitle = i18n.translate('discover.grid.filterOutAria', { - defaultMessage: 'Filter out this {value}', - values: { value: columnId }, - }); - - return ( - { - onFilterCell(context, rowIndex, columnId, '-'); - }} - iconType="minusInCircle" - aria-label={buttonTitle} - title={buttonTitle} - data-test-subj="filterOutButton" - > - {i18n.translate('discover.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', { - defaultMessage: 'Copy value of {column}', - values: { column: columnId }, - }); - - return ( - { - copyValueToClipboard({ - rowIndex, - columnId, - toastNotifications, - valueToStringConverter, - }); - }} - iconType="copyClipboard" - aria-label={buttonTitle} - title={buttonTitle} - data-test-subj="copyClipboardButton" - > - {i18n.translate('discover.grid.copyCellValueButton', { - defaultMessage: 'Copy value', - })} - - ); -}; - -export function buildCellActions(field: DataViewField, onFilter?: DocViewFilterFn) { - return [...(onFilter && field.filterable ? [FilterInBtn, FilterOutBtn] : []), CopyBtn]; -} diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_columns.test.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_columns.test.tsx deleted file mode 100644 index cea7f6c3505c9..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_columns.test.tsx +++ /dev/null @@ -1,533 +0,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 { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { getEuiGridColumns, getVisibleColumns } from './discover_grid_columns'; -import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; -import { discoverGridContextMock } from '../../__mocks__/grid_context'; -import { discoverServiceMock } from '../../__mocks__/services'; - -const columns = ['extension', 'message']; -const columnsWithTimeCol = getVisibleColumns( - ['extension', 'message'], - dataViewWithTimefieldMock, - true -) as string[]; - -describe('Discover grid columns', function () { - describe('getEuiGridColumns', () => { - it('returns eui grid columns showing default columns', async () => { - const actual = getEuiGridColumns({ - columns, - settings: {}, - dataView: dataViewWithTimefieldMock, - defaultColumns: true, - isSortEnabled: true, - isPlainRecord: false, - valueToStringConverter: discoverGridContextMock.valueToStringConverter, - rowsCount: 100, - services: { - uiSettings: discoverServiceMock.uiSettings, - toastNotifications: discoverServiceMock.toastNotifications, - }, - hasEditDataViewPermission: () => - discoverServiceMock.dataViewFieldEditor.userPermissions.editIndexPattern(), - onFilter: () => {}, - }); - expect(actual).toMatchInlineSnapshot(` - Array [ - Object { - "actions": Object { - "additional": Array [ - Object { - "data-test-subj": "gridCopyColumnNameToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - Object { - "data-test-subj": "gridCopyColumnValuesToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - ], - "showHide": false, - "showMoveLeft": false, - "showMoveRight": false, - }, - "cellActions": Array [ - [Function], - [Function], - [Function], - ], - "displayAsText": "extension", - "id": "extension", - "isSortable": false, - "schema": "string", - }, - Object { - "actions": Object { - "additional": Array [ - Object { - "data-test-subj": "gridCopyColumnNameToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - Object { - "data-test-subj": "gridCopyColumnValuesToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - ], - "showHide": false, - "showMoveLeft": false, - "showMoveRight": false, - }, - "cellActions": Array [ - [Function], - ], - "displayAsText": "message", - "id": "message", - "isSortable": false, - "schema": "string", - }, - ] - `); - }); - - it('returns eui grid columns with time column', async () => { - const actual = getEuiGridColumns({ - columns: columnsWithTimeCol, - settings: {}, - dataView: dataViewWithTimefieldMock, - defaultColumns: false, - isSortEnabled: true, - isPlainRecord: false, - valueToStringConverter: discoverGridContextMock.valueToStringConverter, - rowsCount: 100, - services: { - uiSettings: discoverServiceMock.uiSettings, - toastNotifications: discoverServiceMock.toastNotifications, - }, - hasEditDataViewPermission: () => - discoverServiceMock.dataViewFieldEditor.userPermissions.editIndexPattern(), - onFilter: () => {}, - }); - expect(actual).toMatchInlineSnapshot(` - Array [ - Object { - "actions": Object { - "additional": Array [ - Object { - "data-test-subj": "gridCopyColumnNameToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - Object { - "data-test-subj": "gridCopyColumnValuesToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - ], - "showHide": false, - "showMoveLeft": true, - "showMoveRight": true, - }, - "cellActions": Array [ - [Function], - [Function], - [Function], - ], - "display":
    - - - timestamp - - - - -
    , - "displayAsText": "timestamp", - "id": "timestamp", - "initialWidth": 210, - "isSortable": true, - "schema": "datetime", - }, - Object { - "actions": Object { - "additional": Array [ - Object { - "data-test-subj": "gridCopyColumnNameToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - Object { - "data-test-subj": "gridCopyColumnValuesToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - ], - "showHide": Object { - "iconType": "cross", - "label": "Remove column", - }, - "showMoveLeft": true, - "showMoveRight": true, - }, - "cellActions": Array [ - [Function], - [Function], - [Function], - ], - "displayAsText": "extension", - "id": "extension", - "isSortable": false, - "schema": "string", - }, - Object { - "actions": Object { - "additional": Array [ - Object { - "data-test-subj": "gridCopyColumnNameToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - Object { - "data-test-subj": "gridCopyColumnValuesToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - ], - "showHide": Object { - "iconType": "cross", - "label": "Remove column", - }, - "showMoveLeft": true, - "showMoveRight": true, - }, - "cellActions": Array [ - [Function], - ], - "displayAsText": "message", - "id": "message", - "isSortable": false, - "schema": "string", - }, - ] - `); - }); - - it('returns eui grid with in memory sorting', async () => { - const actual = getEuiGridColumns({ - columns: columnsWithTimeCol, - settings: {}, - dataView: dataViewWithTimefieldMock, - defaultColumns: false, - isSortEnabled: true, - isPlainRecord: true, - valueToStringConverter: discoverGridContextMock.valueToStringConverter, - rowsCount: 100, - services: { - uiSettings: discoverServiceMock.uiSettings, - toastNotifications: discoverServiceMock.toastNotifications, - }, - hasEditDataViewPermission: () => - discoverServiceMock.dataViewFieldEditor.userPermissions.editIndexPattern(), - onFilter: () => {}, - }); - expect(actual).toMatchInlineSnapshot(` - Array [ - Object { - "actions": Object { - "additional": Array [ - Object { - "data-test-subj": "gridCopyColumnNameToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - Object { - "data-test-subj": "gridCopyColumnValuesToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - ], - "showHide": false, - "showMoveLeft": true, - "showMoveRight": true, - }, - "cellActions": Array [ - [Function], - [Function], - [Function], - ], - "display":
    - - - timestamp - - - - -
    , - "displayAsText": "timestamp", - "id": "timestamp", - "initialWidth": 210, - "isSortable": true, - "schema": "datetime", - }, - Object { - "actions": Object { - "additional": Array [ - Object { - "data-test-subj": "gridCopyColumnNameToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - Object { - "data-test-subj": "gridCopyColumnValuesToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - ], - "showHide": Object { - "iconType": "cross", - "label": "Remove column", - }, - "showMoveLeft": true, - "showMoveRight": true, - }, - "cellActions": Array [ - [Function], - [Function], - [Function], - ], - "displayAsText": "extension", - "id": "extension", - "isSortable": true, - "schema": "string", - }, - Object { - "actions": Object { - "additional": Array [ - Object { - "data-test-subj": "gridCopyColumnNameToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - Object { - "data-test-subj": "gridCopyColumnValuesToClipBoardButton", - "iconProps": Object { - "size": "m", - }, - "iconType": "copyClipboard", - "label": , - "onClick": [Function], - "size": "xs", - }, - ], - "showHide": Object { - "iconType": "cross", - "label": "Remove column", - }, - "showMoveLeft": true, - "showMoveRight": true, - }, - "cellActions": Array [ - [Function], - ], - "displayAsText": "message", - "id": "message", - "isSortable": true, - "schema": "string", - }, - ] - `); - }); - }); - - describe('getVisibleColumns', () => { - it('returns grid columns without time column when data view has no timestamp field', () => { - const actual = getVisibleColumns(['extension', 'message'], dataViewMock, true) as string[]; - expect(actual).toEqual(['extension', 'message']); - }); - - it('returns grid columns without time column when showTimeCol is falsy', () => { - const actual = getVisibleColumns( - ['extension', 'message'], - dataViewWithTimefieldMock, - false - ) as string[]; - expect(actual).toEqual(['extension', 'message']); - }); - - it('returns grid columns with time column when data view has timestamp field', () => { - const actual = getVisibleColumns( - ['extension', 'message'], - dataViewWithTimefieldMock, - true - ) as string[]; - expect(actual).toEqual(['timestamp', 'extension', 'message']); - }); - }); -}); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_columns.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_columns.tsx deleted file mode 100644 index a93b8a9ff1464..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_columns.tsx +++ /dev/null @@ -1,249 +0,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 { - type EuiDataGridColumn, - type EuiDataGridColumnCellAction, - EuiIcon, - EuiScreenReaderOnly, - EuiToolTip, -} 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 { buildCopyColumnNameButton, buildCopyColumnValuesButton } from './build_copy_column_button'; -import { buildEditFieldButton } from './build_edit_field_button'; - -const openDetails = { - id: 'openDetails', - width: 24, - headerCellRender: () => ( - - - {i18n.translate('discover.controlColumnHeader', { - defaultMessage: 'Control column', - })} - - - ), - rowCellRender: ExpandButton, -}; - -const select = { - id: 'select', - width: 24, - rowCellRender: SelectButton, - headerCellRender: () => ( - - - {i18n.translate('discover.selectColumnHeader', { - defaultMessage: 'Select column', - })} - - - ), -}; - -export function getLeadControlColumns(canSetExpandedDoc: boolean) { - if (!canSetExpandedDoc) { - return [select]; - } - return [openDetails, select]; -} - -function buildEuiGridColumn({ - columnName, - columnWidth = 0, - dataView, - defaultColumns, - isSortEnabled, - isPlainRecord, - toastNotifications, - hasEditDataViewPermission, - valueToStringConverter, - rowsCount, - onFilter, - editField, - columnCellActions, -}: { - columnName: string; - columnWidth: number | undefined; - dataView: DataView; - defaultColumns: boolean; - isSortEnabled: boolean; - isPlainRecord?: boolean; - toastNotifications: ToastsStart; - hasEditDataViewPermission: () => boolean; - valueToStringConverter: ValueToStringConverter; - rowsCount: number; - onFilter?: DocViewFilterFn; - editField?: (fieldName: string) => void; - columnCellActions?: EuiDataGridColumnCellAction[]; -}) { - const dataViewField = dataView.getFieldByName(columnName); - const editFieldButton = - editField && - dataViewField && - buildEditFieldButton({ hasEditDataViewPermission, dataView, field: dataViewField, editField }); - const columnDisplayName = - columnName === '_source' - ? i18n.translate('discover.grid.documentHeader', { - defaultMessage: 'Document', - }) - : dataViewField?.displayName || columnName; - - let cellActions: EuiDataGridColumnCellAction[]; - if (columnCellActions?.length) { - cellActions = columnCellActions; - } else { - cellActions = dataViewField ? buildCellActions(dataViewField, onFilter) : []; - } - - const column: EuiDataGridColumn = { - id: columnName, - schema: getSchemaByKbnType(dataViewField?.type), - isSortable: isSortEnabled && (isPlainRecord || dataViewField?.sortable === true), - displayAsText: columnDisplayName, - actions: { - showHide: - defaultColumns || columnName === dataView.timeFieldName - ? false - : { - label: i18n.translate('discover.removeColumnLabel', { - defaultMessage: 'Remove column', - }), - iconType: 'cross', - }, - showMoveLeft: !defaultColumns, - showMoveRight: !defaultColumns, - additional: [ - ...(columnName === '__source' - ? [] - : [ - buildCopyColumnNameButton({ - columnDisplayName, - toastNotifications, - }), - ]), - buildCopyColumnValuesButton({ - columnId: columnName, - columnDisplayName, - toastNotifications, - rowsCount, - valueToStringConverter, - }), - ...(editFieldButton ? [editFieldButton] : []), - ], - }, - cellActions, - }; - - if (column.id === dataView.timeFieldName) { - const timeFieldName = dataViewField?.customLabel ?? dataView.timeFieldName; - const primaryTimeAriaLabel = i18n.translate( - 'discover.docTable.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.', - } - ); - - column.display = ( -
    - - <> - {timeFieldName} - - -
    - ); - column.initialWidth = defaultTimeColumnWidth; - } - if (columnWidth > 0) { - column.initialWidth = Number(columnWidth); - } - return column; -} - -export function getEuiGridColumns({ - columns, - columnsCellActions, - rowsCount, - settings, - dataView, - defaultColumns, - isSortEnabled, - isPlainRecord, - services, - hasEditDataViewPermission, - valueToStringConverter, - onFilter, - editField, -}: { - columns: string[]; - columnsCellActions?: EuiDataGridColumnCellAction[][]; - rowsCount: number; - settings: DiscoverGridSettings | undefined; - dataView: DataView; - defaultColumns: boolean; - isSortEnabled: boolean; - isPlainRecord?: boolean; - services: { - uiSettings: IUiSettingsClient; - toastNotifications: ToastsStart; - }; - hasEditDataViewPermission: () => boolean; - valueToStringConverter: ValueToStringConverter; - onFilter: DocViewFilterFn; - editField?: (fieldName: string) => void; -}) { - const getColWidth = (column: string) => settings?.columns?.[column]?.width ?? 0; - - return columns.map((column, columnIndex) => - buildEuiGridColumn({ - columnName: column, - columnCellActions: columnsCellActions?.[columnIndex], - columnWidth: getColWidth(column), - dataView, - defaultColumns, - isSortEnabled, - isPlainRecord, - toastNotifications: services.toastNotifications, - hasEditDataViewPermission, - valueToStringConverter, - rowsCount, - onFilter, - editField, - }) - ); -} - -export function getVisibleColumns(columns: string[], dataView: DataView, showTimeCol: boolean) { - const timeFieldName = dataView.timeFieldName; - - if (showTimeCol && timeFieldName && !columns.find((col) => col === timeFieldName)) { - return [timeFieldName, ...columns]; - } - - return columns; -} diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_context.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_context.tsx deleted file mode 100644 index 8ec4689a00178..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_context.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import 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'; - -export interface GridContext { - expanded?: DataTableRecord | undefined; - setExpanded?: (hit?: DataTableRecord) => void; - rows: DataTableRecord[]; - onFilter?: DocViewFilterFn; - dataView: DataView; - isDarkMode: boolean; - selectedDocs: string[]; - setSelectedDocs: (selected: string[]) => void; - valueToStringConverter: ValueToStringConverter; -} - -const defaultContext = {} as unknown as GridContext; - -export const DiscoverGridContext = React.createContext(defaultContext); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.test.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.test.tsx deleted file mode 100644 index 7fda5b74ce550..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.test.tsx +++ /dev/null @@ -1,145 +0,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 { 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 { getDocId } from '@kbn/discover-utils'; - -describe('document selection', () => { - describe('getDocId', () => { - test('doc with custom routing', () => { - const doc = { - _id: 'test-id', - _index: 'test-indices', - _routing: 'why-not', - }; - expect(getDocId(doc)).toMatchInlineSnapshot(`"test-indices::test-id::why-not"`); - }); - test('doc without custom routing', () => { - const doc = { - _id: 'test-id', - _index: 'test-indices', - }; - expect(getDocId(doc)).toMatchInlineSnapshot(`"test-indices::test-id::"`); - }); - }); - - describe('SelectButton', () => { - test('is not checked', () => { - const contextMock = { - ...discoverGridContextMock, - }; - - const component = mountWithIntl( - - - - ); - - const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); - expect(checkBox.props().checked).toBeFalsy(); - }); - - test('is checked', () => { - const contextMock = { - ...discoverGridContextMock, - selectedDocs: ['i::1::'], - }; - - const component = mountWithIntl( - - - - ); - - const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); - expect(checkBox.props().checked).toBeTruthy(); - }); - - test('adding a selection', () => { - const contextMock = { - ...discoverGridContextMock, - }; - - const component = mountWithIntl( - - - - ); - - const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); - checkBox.simulate('change'); - expect(contextMock.setSelectedDocs).toHaveBeenCalledWith(['i::1::']); - }); - test('removing a selection', () => { - const contextMock = { - ...discoverGridContextMock, - selectedDocs: ['i::1::'], - }; - - const component = mountWithIntl( - - - - ); - - const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::'); - checkBox.simulate('change'); - expect(contextMock.setSelectedDocs).toHaveBeenCalledWith([]); - }); - }); - describe('DiscoverGridDocumentToolbarBtn', () => { - test('it renders a button clickable button', () => { - const props = { - isFilterActive: false, - rows: discoverGridContextMock.rows, - selectedDocs: ['i::1::'], - setIsFilterActive: jest.fn(), - setSelectedDocs: jest.fn(), - }; - 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/src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.tsx deleted file mode 100644 index f14ec323f8ca2..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_document_selection.tsx +++ /dev/null @@ -1,189 +0,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, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; -import classNames from 'classnames'; -import { - EuiButtonEmpty, - EuiCheckbox, - EuiContextMenuItem, - EuiContextMenuPanel, - EuiCopy, - EuiDataGridCellValueElementProps, - EuiPopover, -} from '@elastic/eui'; -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'; - -export const SelectButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => { - const { selectedDocs, expanded, rows, isDarkMode, setSelectedDocs } = - useContext(DiscoverGridContext); - const doc = useMemo(() => rows[rowIndex], [rows, rowIndex]); - const checked = useMemo(() => selectedDocs.includes(doc.id), [selectedDocs, doc.id]); - - const toggleDocumentSelectionLabel = i18n.translate('discover.grid.selectDoc', { - defaultMessage: `Select document '{rowNumber}'`, - values: { rowNumber: rowIndex + 1 }, - }); - - useEffect(() => { - if (expanded && doc && expanded.id === doc.id) { - setCellProps({ - style: { - backgroundColor: isDarkMode ? themeDark.euiColorHighlight : themeLight.euiColorHighlight, - }, - }); - } else { - setCellProps({ style: undefined }); - } - }, [expanded, doc, setCellProps, isDarkMode]); - - return ( - { - if (checked) { - const newSelection = selectedDocs.filter((docId) => docId !== doc.id); - setSelectedDocs(newSelection); - } else { - setSelectedDocs([...selectedDocs, doc.id]); - } - }} - /> - ); -}; - -export function DiscoverGridDocumentToolbarBtn({ - isFilterActive, - rows, - selectedDocs, - setIsFilterActive, - setSelectedDocs, -}: { - isFilterActive: boolean; - rows: DataTableRecord[]; - selectedDocs: string[]; - setIsFilterActive: (value: boolean) => void; - setSelectedDocs: (value: string[]) => void; -}) { - const [isSelectionPopoverOpen, setIsSelectionPopoverOpen] = useState(false); - - const getMenuItems = useCallback(() => { - return [ - isFilterActive ? ( - { - setIsSelectionPopoverOpen(false); - setIsFilterActive(false); - }} - > - - - ) : ( - { - setIsSelectionPopoverOpen(false); - setIsFilterActive(true); - }} - > - - - ), - selectedDocs.includes(row.id)).map((row) => row.raw) - ) - : '' - } - > - {(copy) => ( - - - - )} - , - { - setIsSelectionPopoverOpen(false); - setSelectedDocs([]); - setIsFilterActive(false); - }} - > - - , - ]; - }, [ - isFilterActive, - rows, - selectedDocs, - setIsFilterActive, - setIsSelectionPopoverOpen, - setSelectedDocs, - ]); - - const toggleSelectionToolbar = useCallback( - () => setIsSelectionPopoverOpen((prevIsOpen) => !prevIsOpen), - [] - ); - - return ( - setIsSelectionPopoverOpen(false)} - isOpen={isSelectionPopoverOpen} - panelPaddingSize="none" - button={ - - - - } - > - {isSelectionPopoverOpen && } - - ); -} diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.test.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.test.tsx deleted file mode 100644 index e95853b99b7b7..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.test.tsx +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import 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'; - -describe('Discover grid view button ', function () { - it('when no document is expanded, setExpanded is called with current document', async () => { - const contextMock = { - ...discoverGridContextMock, - }; - - const component = mountWithIntl( - - - - ); - const button = findTestSubject(component, 'docTableExpandToggleColumn'); - await button.simulate('click'); - expect(contextMock.setExpanded).toHaveBeenCalledWith(discoverGridContextMock.rows[0]); - }); - it('when the current document is expanded, setExpanded is called with undefined', async () => { - const contextMock = { - ...discoverGridContextMock, - expanded: discoverGridContextMock.rows[0], - }; - - const component = mountWithIntl( - - - - ); - const button = findTestSubject(component, 'docTableExpandToggleColumn'); - await button.simulate('click'); - expect(contextMock.setExpanded).toHaveBeenCalledWith(undefined); - }); - it('when another document is expanded, setExpanded is called with the current document', async () => { - const contextMock = { - ...discoverGridContextMock, - expanded: discoverGridContextMock.rows[0], - }; - - const component = mountWithIntl( - - - - ); - const button = findTestSubject(component, 'docTableExpandToggleColumn'); - await button.simulate('click'); - expect(contextMock.setExpanded).toHaveBeenCalledWith(discoverGridContextMock.rows[1]); - }); -}); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx deleted file mode 100644 index 1a127f3639432..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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, { 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'; - -/** - * Button to expand a given row - */ -export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => { - const toolTipRef = useRef(null); - const [pressed, setPressed] = useState(false); - const { expanded, setExpanded, rows, isDarkMode } = useContext(DiscoverGridContext); - const current = rows[rowIndex]; - - useEffect(() => { - if (current.isAnchor) { - setCellProps({ - className: 'dscDocsGrid__cell--highlight', - }); - } else if (expanded && current && expanded.id === current.id) { - setCellProps({ - style: { - backgroundColor: isDarkMode ? themeDark.euiColorHighlight : themeLight.euiColorHighlight, - }, - }); - } else { - setCellProps({ style: undefined }); - } - }, [expanded, current, setCellProps, isDarkMode]); - - const isCurrentRowExpanded = current === expanded; - const buttonLabel = i18n.translate('discover.grid.viewDoc', { - defaultMessage: 'Toggle dialog with details', - }); - - const testSubj = current.isAnchor - ? 'docTableExpandToggleColumnAnchor' - : 'docTableExpandToggleColumn'; - - useEffect(() => { - if (!isCurrentRowExpanded && pressed) { - setPressed(false); - setTimeout(() => { - toolTipRef.current?.hideToolTip(); - }, 100); - } - }, [isCurrentRowExpanded, setPressed, pressed]); - - if (!setExpanded) { - return null; - } - - return ( - - { - const nextHit = isCurrentRowExpanded ? undefined : current; - toolTipRef.current?.hideToolTip(); - setPressed(Boolean(nextHit)); - setExpanded?.(nextHit); - }} - color={isCurrentRowExpanded ? 'primary' : 'text'} - iconType={isCurrentRowExpanded ? 'minimize' : 'expand'} - isSelected={isCurrentRowExpanded} - /> - - ); -}; diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_footer.test.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_footer.test.tsx deleted file mode 100644 index a4bfe84b68126..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_footer.test.tsx +++ /dev/null @@ -1,138 +0,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 { mountWithIntl } from '@kbn/test-jest-helpers'; -import { findTestSubject } from '@elastic/eui/lib/test'; -import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { DiscoverGridFooter } from './discover_grid_footer'; -import { discoverServiceMock } from '../../__mocks__/services'; - -describe('DiscoverGridFooter', function () { - it('should not render anything when not on the last page', async () => { - const component = mountWithIntl( - - - - ); - expect(component.isEmptyRender()).toBe(true); - }); - - 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( - 'Search results are limited to 500 documents. Add more search terms to narrow your search.' - ); - expect(findTestSubject(component, 'dscGridSampleSizeFetchMoreLink').exists()).toBe(false); - }); - - it('should render a message and the button for the last page', async () => { - const mockLoadMore = jest.fn(); - - const component = mountWithIntl( - - - - ); - expect(findTestSubject(component, 'discoverTableFooter').text()).toBe( - 'Search results are limited to 500 documents.Load more' - ); - - const button = findTestSubject(component, 'dscGridSampleSizeFetchMoreLink'); - expect(button.exists()).toBe(true); - - button.simulate('click'); - - expect(mockLoadMore).toHaveBeenCalledTimes(1); - }); - - it('should render a disabled button when loading more', async () => { - const mockLoadMore = jest.fn(); - - const component = mountWithIntl( - - - - ); - expect(findTestSubject(component, 'discoverTableFooter').text()).toBe( - 'Search results are limited to 500 documents.Load more' - ); - - const button = findTestSubject(component, 'dscGridSampleSizeFetchMoreLink'); - expect(button.exists()).toBe(true); - expect(button.prop('disabled')).toBe(true); - - button.simulate('click'); - - expect(mockLoadMore).not.toHaveBeenCalled(); - }); - - it('should render a message when max total limit is reached', async () => { - const component = mountWithIntl( - - - - ); - expect(findTestSubject(component, 'discoverTableFooter').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/src/plugins/discover/public/components/discover_grid/discover_grid_footer.tsx deleted file mode 100644 index 540c7102bd424..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_footer.tsx +++ /dev/null @@ -1,161 +0,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, useState } from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -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'; - -export interface DiscoverGridFooterProps { - isLoadingMore?: boolean; - rowCount: number; - sampleSize: number; - pageIndex?: number; // starts from 0 - pageCount: number; - totalHits?: number; - onFetchMoreRecords?: () => void; -} - -export const DiscoverGridFooter: React.FC = (props) => { - const { - isLoadingMore, - rowCount, - sampleSize, - pageIndex, - pageCount, - totalHits = 0, - onFetchMoreRecords, - } = props; - const { data } = useDiscoverServices(); - const timefilter = data.query.timefilter.timefilter; - const [refreshInterval, setRefreshInterval] = useState(timefilter.getRefreshInterval()); - - useEffect(() => { - const subscriber = timefilter.getRefreshIntervalUpdate$().subscribe(() => { - setRefreshInterval(timefilter.getRefreshInterval()); - }); - - return () => subscriber.unsubscribe(); - }, [timefilter, setRefreshInterval]); - - const isRefreshIntervalOn = Boolean( - refreshInterval && refreshInterval.pause === false && refreshInterval.value > 0 - ); - - const { euiTheme } = useEuiTheme(); - const isOnLastPage = pageIndex === pageCount - 1 && rowCount < totalHits; - - if (!isOnLastPage) { - return null; - } - - // allow to fetch more records on Discover page - if (onFetchMoreRecords && typeof isLoadingMore === 'boolean') { - if (rowCount <= MAX_LOADED_GRID_ROWS - sampleSize) { - return ( - - - - - - - - ); - } - - return ; - } - - if (rowCount < totalHits) { - // show only a message for embeddable - return ; - } - - return null; -}; - -interface DiscoverGridFooterContainerProps extends DiscoverGridFooterProps { - hasButton: boolean; -} - -const DiscoverGridFooterContainer: React.FC = ({ - hasButton, - rowCount, - children, -}) => { - const { euiTheme } = useEuiTheme(); - const { fieldFormats } = useDiscoverServices(); - - const formattedRowCount = fieldFormats - .getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER]) - .convert(rowCount); - - return ( -

    - - {hasButton ? ( - - ) : ( - - )} - - {children} -

    - ); -}; diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_schema.ts b/src/plugins/discover/public/components/discover_grid/discover_grid_schema.ts deleted file mode 100644 index dde4be2e76841..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_schema.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { KBN_FIELD_TYPES } from '@kbn/data-plugin/public'; -import { kibanaJSON } from './constants'; - -export function getSchemaByKbnType(kbnType: string | undefined) { - // Default DataGrid schemas: boolean, numeric, datetime, json, currency, string - switch (kbnType) { - case KBN_FIELD_TYPES.IP: - case KBN_FIELD_TYPES.GEO_SHAPE: - case KBN_FIELD_TYPES.NUMBER: - return 'numeric'; - case KBN_FIELD_TYPES.BOOLEAN: - return 'boolean'; - case KBN_FIELD_TYPES.STRING: - return 'string'; - case KBN_FIELD_TYPES.DATE: - return 'datetime'; - default: - return kibanaJSON; - } -} - -export function getSchemaDetectors() { - return [ - { - type: kibanaJSON, - detector() { - return 0; // this schema is always explicitly defined - }, - sortTextAsc: '', - sortTextDesc: '', - icon: '', - color: '', - }, - ]; -} diff --git a/src/plugins/discover/public/components/discover_grid/types.ts b/src/plugins/discover/public/components/discover_grid/types.ts deleted file mode 100644 index 71d82e35126ac..0000000000000 --- a/src/plugins/discover/public/components/discover_grid/types.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -/** - * User configurable state of data grid, persisted in saved search - */ -export interface DiscoverGridSettings { - columns?: Record; -} - -export interface DiscoverGridSettingsColumn { - width?: number; -} 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/actions/columns.test.ts b/src/plugins/discover/public/components/doc_table/actions/columns.test.ts deleted file mode 100644 index c95ff0d8d7252..0000000000000 --- a/src/plugins/discover/public/components/doc_table/actions/columns.test.ts +++ /dev/null @@ -1,82 +0,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 { 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'; - -function getStateColumnAction( - state: DiscoverAppState, - setAppState: (state: Partial) => void -) { - return getStateColumnActions({ - capabilities: { - discover: { - save: false, - }, - } as unknown as Capabilities, - config: configMock, - dataView: dataViewMock, - dataViews: dataViewsMock, - useNewFieldsApi: true, - setAppState, - columns: state.columns, - sort: state.sort, - }); -} - -describe('Test column actions', () => { - test('getStateColumnActions with empty state', () => { - const setAppState = jest.fn(); - const actions = getStateColumnAction({}, setAppState); - - actions.onAddColumn('_score'); - expect(setAppState).toHaveBeenCalledWith({ columns: ['_score'], sort: [['_score', 'desc']] }); - actions.onAddColumn('test'); - expect(setAppState).toHaveBeenCalledWith({ columns: ['test'] }); - }); - test('getStateColumnActions with columns and sort in state', () => { - const setAppState = jest.fn(); - const actions = getStateColumnAction( - { columns: ['first', 'second'], sort: [['first', 'desc']] }, - setAppState - ); - - actions.onAddColumn('_score'); - expect(setAppState).toHaveBeenCalledWith({ - columns: ['first', 'second', '_score'], - sort: [['first', 'desc']], - }); - setAppState.mockClear(); - actions.onAddColumn('third'); - expect(setAppState).toHaveBeenCalledWith({ - columns: ['first', 'second', 'third'], - sort: [['first', 'desc']], - }); - setAppState.mockClear(); - actions.onRemoveColumn('first'); - expect(setAppState).toHaveBeenCalledWith({ - columns: ['second'], - sort: [], - }); - setAppState.mockClear(); - actions.onSetColumns(['first', 'second', 'third'], true); - expect(setAppState).toHaveBeenCalledWith({ - columns: ['first', 'second', 'third'], - }); - setAppState.mockClear(); - - actions.onMoveColumn('second', 0); - expect(setAppState).toHaveBeenCalledWith({ - columns: ['second', 'first'], - }); - }); -}); diff --git a/src/plugins/discover/public/components/doc_table/actions/columns.ts b/src/plugins/discover/public/components/doc_table/actions/columns.ts deleted file mode 100644 index b45d95433165a..0000000000000 --- a/src/plugins/discover/public/components/doc_table/actions/columns.ts +++ /dev/null @@ -1,113 +0,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 { 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'; - -/** - * Helper function to provide a fallback to a single _source column if the given array of columns - * is empty, and removes _source if there are more than 1 columns given - * @param columns - * @param useNewFieldsApi should a new fields API be used - */ -function buildColumns(columns: string[], useNewFieldsApi = false) { - if (columns.length > 1 && columns.indexOf('_source') !== -1) { - return columns.filter((col) => col !== '_source'); - } else if (columns.length !== 0) { - return columns; - } - return useNewFieldsApi ? [] : ['_source']; -} - -export function addColumn(columns: string[], columnName: string, useNewFieldsApi?: boolean) { - if (columns.includes(columnName)) { - return columns; - } - return buildColumns([...columns, columnName], useNewFieldsApi); -} - -export function removeColumn(columns: string[], columnName: string, useNewFieldsApi?: boolean) { - if (!columns.includes(columnName)) { - return columns; - } - return buildColumns( - columns.filter((col) => col !== columnName), - useNewFieldsApi - ); -} - -export function moveColumn(columns: string[], columnName: string, newIndex: number) { - if (newIndex < 0 || newIndex >= columns.length || !columns.includes(columnName)) { - return columns; - } - const modifiedColumns = [...columns]; - modifiedColumns.splice(modifiedColumns.indexOf(columnName), 1); // remove at old index - modifiedColumns.splice(newIndex, 0, columnName); // insert before new index - return modifiedColumns; -} - -export function getStateColumnActions({ - capabilities, - config, - dataView, - dataViews, - useNewFieldsApi, - setAppState, - columns, - sort, -}: { - capabilities: Capabilities; - config: IUiSettingsClient; - dataView: DataView; - dataViews: DataViewsContract; - useNewFieldsApi: boolean; - setAppState: DiscoverAppStateContainer['update'] | ContextGetStateReturn['setAppState']; - columns?: string[]; - sort: string[][] | undefined; -}) { - 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 }); - } - - function onRemoveColumn(columnName: string) { - popularizeField(dataView, columnName, dataViews, capabilities); - const nextColumns = removeColumn(columns || [], columnName, useNewFieldsApi); - // The state's sort property is an array of [sortByColumn,sortDirection] - const nextSort = sort && sort.length ? sort.filter((subArr) => subArr[0] !== columnName) : []; - setAppState({ columns: nextColumns, sort: nextSort }); - } - - function onMoveColumn(columnName: string, newIndex: number) { - const nextColumns = moveColumn(columns || [], columnName, newIndex); - setAppState({ columns: nextColumns }); - } - - function onSetColumns(nextColumns: string[], hideTimeColumn: boolean) { - // The next line should be gone when classic table will be removed - const actualColumns = - !hideTimeColumn && dataView.timeFieldName && dataView.timeFieldName === nextColumns[0] - ? (nextColumns || []).slice(1) - : nextColumns; - - setAppState({ columns: actualColumns }); - } - return { - onAddColumn, - onRemoveColumn, - onMoveColumn, - onSetColumns, - }; -} 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 a38e082778a68..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( @@ -186,7 +184,9 @@ export const TableRow = ({ // We should improve this and show a helpful tooltip why the filter buttons are not // there/disabled when there are ignored values. const isFilterable = Boolean( - mapping(column)?.filterable && filter && !row.raw._ignored?.includes(column) + mapping(column)?.filterable && + typeof filter === 'function' && + !row.raw._ignored?.includes(column) ); rowCells.push( - ); 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/components/index.ts b/src/plugins/discover/public/components/index.ts deleted file mode 100644 index a794b8c90a477..0000000000000 --- a/src/plugins/discover/public/components/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { DeferredSpinner } from './common/deferred_spinner'; diff --git a/src/plugins/discover/public/components/json_code_editor/json_code_editor.test.tsx b/src/plugins/discover/public/components/json_code_editor/json_code_editor.test.tsx deleted file mode 100644 index 9ec60410b591e..0000000000000 --- a/src/plugins/discover/public/components/json_code_editor/json_code_editor.test.tsx +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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/discover/public/components/json_code_editor/json_code_editor.tsx b/src/plugins/discover/public/components/json_code_editor/json_code_editor.tsx deleted file mode 100644 index 426a180d37957..0000000000000 --- a/src/plugins/discover/public/components/json_code_editor/json_code_editor.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import './json_code_editor.scss'; - -import React from 'react'; -import { JsonCodeEditorCommon } from './json_code_editor_common'; - -interface JsonCodeEditorProps { - json: Record; - width?: string | number; - height?: string | number; - hasLineNumbers?: boolean; -} - -export const 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/discover/public/components/json_code_editor/json_code_editor_common.tsx deleted file mode 100644 index 777240fe2f5bb..0000000000000 --- a/src/plugins/discover/public/components/json_code_editor/json_code_editor_common.tsx +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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/kibana-react-plugin/public'; - -const codeEditorAriaLabel = i18n.translate('discover.json.codeEditorAriaLabel', { - defaultMessage: 'Read only JSON view of an elasticsearch document', -}); -const copyToClipboardLabel = i18n.translate('discover.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/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_data_grid_columns.ts b/src/plugins/discover/public/hooks/use_data_grid_columns.ts deleted file mode 100644 index 22fc8e9836888..0000000000000 --- a/src/plugins/discover/public/hooks/use_data_grid_columns.ts +++ /dev/null @@ -1,76 +0,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 { useEffect, useMemo, useState } from 'react'; -import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'; - -import { Capabilities, IUiSettingsClient } 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'; - -interface UseColumnsProps { - capabilities: Capabilities; - config: IUiSettingsClient; - dataView: DataView; - dataViews: DataViewsContract; - useNewFieldsApi: boolean; - setAppState: DiscoverAppStateContainer['update'] | ContextGetStateReturn['setAppState']; - columns?: string[]; - sort?: string[][]; -} - -export const useColumns = ({ - capabilities, - config, - dataView, - dataViews, - setAppState, - useNewFieldsApi, - columns, - sort, -}: UseColumnsProps) => { - const [usedColumns, setUsedColumns] = useState(getColumns(columns, useNewFieldsApi)); - useEffect(() => { - const nextColumns = getColumns(columns, useNewFieldsApi); - if (isEqual(usedColumns, nextColumns)) { - return; - } - setUsedColumns(nextColumns); - }, [columns, useNewFieldsApi, usedColumns]); - const { onAddColumn, onRemoveColumn, onSetColumns, onMoveColumn } = useMemo( - () => - getStateColumnActions({ - capabilities, - config, - dataView, - dataViews, - setAppState, - useNewFieldsApi, - columns: usedColumns, - sort, - }), - [capabilities, config, dataView, dataViews, setAppState, sort, useNewFieldsApi, usedColumns] - ); - - return { - columns: usedColumns, - onAddColumn, - onRemoveColumn, - onMoveColumn, - onSetColumns, - }; -}; - -function getColumns(columns: string[] | undefined, useNewFieldsApi: boolean) { - if (!columns) { - return []; - } - return useNewFieldsApi ? columns.filter((col) => col !== '_source') : columns; -} 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/public/services/doc_views/components/doc_viewer/doc_viewer.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer.tsx deleted file mode 100644 index c2532735641f9..0000000000000 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer/doc_viewer.tsx +++ /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 and the Server Side Public License, v 1; you may 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 { EuiTabbedContent } from '@elastic/eui'; -import { getDocViewsRegistry } from '../../../../kibana_services'; -import { DocViewerTab } from './doc_viewer_tab'; -import { DocView, DocViewRenderProps } from '../../doc_views_types'; - -/** - * Rendering tabs with different views of 1 Elasticsearch hit in Discover. - * The tabs are provided by the `docs_views` registry. - * 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}`, - }; - }); - - if (!tabs.length) { - // There there's a minimum of 2 tabs active in Discover. - // This condition takes care of unit tests with 0 tabs. - return null; - } - - return ( -
    - -
    - ); -} diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx deleted file mode 100644 index 1d465978b17b1..0000000000000 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table.tsx +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 '../table.scss'; -import React, { useCallback, useMemo } from 'react'; -import { EuiInMemoryTable } from '@elastic/eui'; -import { getFieldIconType } from '@kbn/unified-field-list/src/utils/field_types/get_field_icon_type'; -import { - SHOW_MULTIFIELDS, - formatFieldValue, - getIgnoredReason, - getShouldShowFieldHandler, - isNestedFieldParent, -} from '@kbn/discover-utils'; -import { useDiscoverServices } from '../../../../../hooks/use_discover_services'; -import { DocViewRenderProps, FieldRecordLegacy } from '../../../doc_views_types'; -import { ACTIONS_COLUMN, MAIN_COLUMNS } from './table_columns'; - -export const DocViewerLegacyTable = ({ - columns, - hit, - dataView, - filter, - onAddColumn, - onRemoveColumn, -}: DocViewRenderProps) => { - const { fieldFormats, uiSettings } = useDiscoverServices(); - const showMultiFields = useMemo(() => uiSettings.get(SHOW_MULTIFIELDS), [uiSettings]); - - const mapping = useCallback((name: string) => dataView.fields.getByName(name), [dataView.fields]); - const tableColumns = useMemo(() => { - return filter ? [ACTIONS_COLUMN, ...MAIN_COLUMNS] : MAIN_COLUMNS; - }, [filter]); - const onToggleColumn = useCallback( - (field: string) => { - if (!onRemoveColumn || !onAddColumn || !columns) { - return; - } - if (columns.includes(field)) { - onRemoveColumn(field); - } else { - onAddColumn(field); - } - }, - [onRemoveColumn, onAddColumn, columns] - ); - - const onSetRowProps = useCallback(({ field: { field } }: FieldRecordLegacy) => { - return { - key: field, - className: 'kbnDocViewer__tableRow', - 'data-test-subj': `tableDocViewRow-${field}`, - }; - }, []); - - const shouldShowFieldHandler = useMemo( - () => getShouldShowFieldHandler(Object.keys(hit.flattened), dataView, showMultiFields), - [hit.flattened, dataView, showMultiFields] - ); - - const items: FieldRecordLegacy[] = Object.keys(hit.flattened) - .filter(shouldShowFieldHandler) - .sort((fieldA, fieldB) => { - const mappingA = mapping(fieldA); - const mappingB = mapping(fieldB); - const nameA = !mappingA || !mappingA.displayName ? fieldA : mappingA.displayName; - const nameB = !mappingB || !mappingB.displayName ? fieldB : mappingB.displayName; - return nameA.localeCompare(nameB); - }) - .map((field) => { - const fieldMapping = mapping(field); - const displayName = fieldMapping?.displayName ?? field; - const fieldType = isNestedFieldParent(field, dataView) - ? 'nested' - : fieldMapping - ? getFieldIconType(fieldMapping) - : undefined; - const ignored = getIgnoredReason(fieldMapping ?? field, hit.raw._ignored); - return { - action: { - onToggleColumn, - onFilter: filter, - isActive: !!columns?.includes(field), - flattenedField: hit.flattened[field], - }, - field: { - field, - displayName, - fieldMapping, - fieldType, - scripted: Boolean(fieldMapping?.scripted), - }, - value: { - formattedValue: formatFieldValue( - hit.flattened[field], - hit.raw, - fieldFormats, - dataView, - fieldMapping - ), - ignored, - }, - }; - }); - - return ( - - ); -}; diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_cell_actions.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_cell_actions.tsx deleted file mode 100644 index 3ce4b789bd1ff..0000000000000 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_cell_actions.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { DataViewField } from '@kbn/data-views-plugin/public'; -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; - isActive: boolean; - flattenedField: unknown; - fieldMapping?: DataViewField; - onFilter: DocViewFilterFn; - onToggleColumn: (field: string) => void; - ignoredValue: boolean; -} - -export const TableActions = ({ - isActive, - field, - fieldMapping, - flattenedField, - onToggleColumn, - onFilter, - ignoredValue, -}: TableActionsProps) => { - return ( -
    - onFilter(fieldMapping, flattenedField, '+')} - /> - onFilter(fieldMapping, flattenedField, '-')} - /> - onToggleColumn(field)} - /> - onFilter('_exists_', field, '+')} - scripted={fieldMapping && fieldMapping.scripted} - /> -
    - ); -}; diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_row_btn_collapse.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_row_btn_collapse.tsx deleted file mode 100644 index 3322d17059136..0000000000000 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_row_btn_collapse.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiToolTip, EuiButtonIcon } from '@elastic/eui'; - -export interface Props { - onClick: () => void; - isCollapsed: boolean; -} - -export function DocViewTableRowBtnCollapse({ onClick, isCollapsed }: Props) { - const label = i18n.translate('discover.docViews.table.toggleFieldDetails', { - defaultMessage: 'Toggle field details', - }); - return ( - - onClick()} - iconType={isCollapsed ? 'arrowRight' : 'arrowDown'} - iconSize={'s'} - /> - - ); -} diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_row_btn_toggle_column.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_row_btn_toggle_column.tsx deleted file mode 100644 index 0ed073046b115..0000000000000 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/legacy/table_row_btn_toggle_column.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { i18n } from '@kbn/i18n'; -import { EuiToolTip, EuiButtonIcon } from '@elastic/eui'; - -export interface Props { - active: boolean; - disabled?: boolean; - onClick: () => void; - fieldname: string; -} - -export function DocViewTableRowBtnToggleColumn({ - onClick, - active, - disabled = false, - fieldname = '', -}: Props) { - if (disabled) { - return ( - - ); - } - return ( - - } - > - - - ); -} diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx deleted file mode 100644 index de13406d64910..0000000000000 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx +++ /dev/null @@ -1,434 +0,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 './table.scss'; -import React, { useCallback, useMemo, useState } from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiFieldSearch, - EuiSpacer, - EuiTable, - EuiTableBody, - EuiTableRowCell, - EuiTableRow, - EuiTableHeader, - EuiTableHeaderCell, - EuiText, - EuiTablePagination, - EuiSelectableMessage, - EuiI18n, - useIsWithinBreakpoints, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { debounce } from 'lodash'; -import { Storage } from '@kbn/kibana-utils-plugin/public'; -import { getFieldIconType } from '@kbn/unified-field-list/src/utils/field_types/get_field_icon_type'; -import { - SHOW_MULTIFIELDS, - formatFieldValue, - getIgnoredReason, - getShouldShowFieldHandler, - isNestedFieldParent, - usePager, -} from '@kbn/discover-utils'; -import { useDiscoverServices } from '../../../../hooks/use_discover_services'; -import { FieldName } from '../../../../components/field_name/field_name'; -import { DocViewRenderProps, FieldRecordLegacy } from '../../doc_views_types'; -import { TableFieldValue } from './table_cell_value'; -import { TableActions } from './table_cell_actions'; - -export interface FieldRecord { - action: Omit; - field: { - pinned: boolean; - onTogglePinned: (field: string) => void; - } & FieldRecordLegacy['field']; - value: FieldRecordLegacy['value']; -} - -interface ItemsEntry { - pinnedItems: FieldRecord[]; - restItems: FieldRecord[]; -} - -const MOBILE_OPTIONS = { header: false }; -const PAGE_SIZE_OPTIONS = [25, 50, 100]; -const DEFAULT_PAGE_SIZE = 25; -const PINNED_FIELDS_KEY = 'discover:pinnedFields'; -const PAGE_SIZE = 'discover:pageSize'; -const SEARCH_TEXT = 'discover:searchText'; - -const getPinnedFields = (dataViewId: string, storage: Storage): string[] => { - const pinnedFieldsEntry = storage.get(PINNED_FIELDS_KEY); - if ( - typeof pinnedFieldsEntry === 'object' && - pinnedFieldsEntry !== null && - Array.isArray(pinnedFieldsEntry[dataViewId]) - ) { - return pinnedFieldsEntry[dataViewId].filter((cur: unknown) => typeof cur === 'string'); - } - return []; -}; -const updatePinnedFieldsState = (newFields: string[], dataViewId: string, storage: Storage) => { - let pinnedFieldsEntry = storage.get(PINNED_FIELDS_KEY); - pinnedFieldsEntry = - typeof pinnedFieldsEntry === 'object' && pinnedFieldsEntry !== null ? pinnedFieldsEntry : {}; - - storage.set(PINNED_FIELDS_KEY, { - ...pinnedFieldsEntry, - [dataViewId]: newFields, - }); -}; - -const getPageSize = (storage: Storage): number => { - const pageSize = Number(storage.get(PAGE_SIZE)); - return pageSize && PAGE_SIZE_OPTIONS.includes(pageSize) ? pageSize : DEFAULT_PAGE_SIZE; -}; -const updatePageSize = (newPageSize: number, storage: Storage) => { - storage.set(PAGE_SIZE, newPageSize); -}; - -const getSearchText = (storage: Storage) => { - return storage.get(SEARCH_TEXT) || ''; -}; -const updateSearchText = debounce( - (newSearchText: string, storage: Storage) => storage.set(SEARCH_TEXT, newSearchText), - 500 -); - -export const DocViewerTable = ({ - columns, - hit, - dataView, - filter, - onAddColumn, - onRemoveColumn, -}: DocViewRenderProps) => { - const showActionsInsideTableCell = useIsWithinBreakpoints(['xl'], true); - - const { storage, uiSettings, fieldFormats } = useDiscoverServices(); - const showMultiFields = uiSettings.get(SHOW_MULTIFIELDS); - const currentDataViewId = dataView.id!; - const isSingleDocView = !filter; - - const [searchText, setSearchText] = useState(getSearchText(storage)); - const [pinnedFields, setPinnedFields] = useState( - getPinnedFields(currentDataViewId, storage) - ); - - const flattened = hit.flattened; - const shouldShowFieldHandler = useMemo( - () => getShouldShowFieldHandler(Object.keys(flattened), dataView, showMultiFields), - [flattened, dataView, showMultiFields] - ); - - const searchPlaceholder = i18n.translate('discover.docView.table.searchPlaceHolder', { - defaultMessage: 'Search field names', - }); - - const mapping = useCallback((name: string) => dataView.fields.getByName(name), [dataView.fields]); - - const onToggleColumn = useCallback( - (field: string) => { - if (!onRemoveColumn || !onAddColumn || !columns) { - return; - } - if (columns.includes(field)) { - onRemoveColumn(field); - } else { - onAddColumn(field); - } - }, - [onRemoveColumn, onAddColumn, columns] - ); - - const onTogglePinned = useCallback( - (field: string) => { - const newPinned = pinnedFields.includes(field) - ? pinnedFields.filter((curField) => curField !== field) - : [...pinnedFields, field]; - - updatePinnedFieldsState(newPinned, currentDataViewId, storage); - setPinnedFields(newPinned); - }, - [currentDataViewId, pinnedFields, storage] - ); - - const fieldToItem = useCallback( - (field: string) => { - const fieldMapping = mapping(field); - const displayName = fieldMapping?.displayName ?? field; - const fieldType = isNestedFieldParent(field, dataView) - ? 'nested' - : fieldMapping - ? getFieldIconType(fieldMapping) - : undefined; - - const ignored = getIgnoredReason(fieldMapping ?? field, hit.raw._ignored); - - return { - action: { - onToggleColumn, - onFilter: filter, - isActive: !!columns?.includes(field), - flattenedField: flattened[field], - }, - field: { - field, - displayName, - fieldMapping, - fieldType, - scripted: Boolean(fieldMapping?.scripted), - pinned: pinnedFields.includes(displayName), - onTogglePinned, - }, - value: { - formattedValue: formatFieldValue( - hit.flattened[field], - hit.raw, - fieldFormats, - dataView, - fieldMapping - ), - ignored, - }, - }; - }, - [ - mapping, - dataView, - hit, - onToggleColumn, - filter, - columns, - flattened, - pinnedFields, - onTogglePinned, - fieldFormats, - ] - ); - - const handleOnChange = useCallback( - (event: React.ChangeEvent) => { - const newSearchText = event.currentTarget.value; - updateSearchText(newSearchText, storage); - setSearchText(newSearchText); - }, - [storage] - ); - - const { pinnedItems, restItems } = Object.keys(flattened) - .sort((fieldA, fieldB) => { - const mappingA = mapping(fieldA); - const mappingB = mapping(fieldB); - const nameA = !mappingA || !mappingA.displayName ? fieldA : mappingA.displayName; - const nameB = !mappingB || !mappingB.displayName ? fieldB : mappingB.displayName; - return nameA.localeCompare(nameB); - }) - .reduce( - (acc, curFieldName) => { - if (!shouldShowFieldHandler(curFieldName)) { - return acc; - } - - if (pinnedFields.includes(curFieldName)) { - acc.pinnedItems.push(fieldToItem(curFieldName)); - } else { - const fieldMapping = mapping(curFieldName); - const displayName = fieldMapping?.displayName ?? curFieldName; - if (displayName.toLowerCase().includes(searchText.toLowerCase())) { - // filter only unpinned fields - acc.restItems.push(fieldToItem(curFieldName)); - } - } - - return acc; - }, - { - pinnedItems: [], - restItems: [], - } - ); - - const { curPageIndex, pageSize, totalPages, startIndex, changePageIndex, changePageSize } = - usePager({ - initialPageSize: getPageSize(storage), - totalItems: restItems.length, - }); - const showPagination = totalPages !== 0; - - const onChangePageSize = useCallback( - (newPageSize: number) => { - updatePageSize(newPageSize, storage); - changePageSize(newPageSize); - }, - [changePageSize, storage] - ); - - const headers = [ - !isSingleDocView && ( - - - - - - - - ), - - - - - - - , - - - - - - - , - ]; - - const renderRows = useCallback( - (items: FieldRecord[]) => { - const highlight = searchText?.toLowerCase(); - return items.map( - ({ - action: { flattenedField, onFilter }, - field: { field, fieldMapping, fieldType, scripted, pinned }, - value: { formattedValue, ignored }, - }: FieldRecord) => { - return ( - - {!isSingleDocView && ( - - - - )} - - - - - - - - ); - } - ); - }, - [onToggleColumn, onTogglePinned, isSingleDocView, showActionsInsideTableCell, searchText] - ); - - const rowElements = [ - ...renderRows(pinnedItems), - ...renderRows(restItems.slice(startIndex, pageSize + startIndex)), - ]; - - return ( - - - - - - - - - - {rowElements.length === 0 ? ( - -

    - -

    -
    - ) : ( - - - {headers} - {rowElements} - - - )} - - - - - - {showPagination && ( - - - - )} -
    - ); -}; diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx deleted file mode 100644 index 9f29f3ba7f69f..0000000000000 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx +++ /dev/null @@ -1,226 +0,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, { useCallback, useState } from 'react'; -import { - EuiButtonIcon, - EuiContextMenu, - EuiPopover, - EuiFlexGroup, - EuiFlexItem, - EuiToolTip, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import type { DataViewField } from '@kbn/data-views-plugin/public'; -import { DocViewFilterFn } from '../../doc_views_types'; - -interface TableActionsProps { - mode?: 'inline' | 'as_popover'; - field: string; - pinned: boolean; - flattenedField: unknown; - fieldMapping?: DataViewField; - onFilter: DocViewFilterFn; - onToggleColumn: (field: string) => void; - ignoredValue: boolean; - onTogglePinned: (field: string) => void; -} - -export const TableActions = ({ - mode = 'as_popover', - pinned, - field, - fieldMapping, - flattenedField, - onToggleColumn, - onFilter, - ignoredValue, - onTogglePinned, -}: TableActionsProps) => { - const [isOpen, setIsOpen] = useState(false); - const openActionsLabel = i18n.translate('discover.docView.table.actions.open', { - defaultMessage: 'Open actions', - }); - const actionsLabel = i18n.translate('discover.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 filterAddAriaLabel = i18n.translate( - 'discover.docViews.table.filterForValueButtonAriaLabel', - { defaultMessage: 'Filter for value' } - ); - const filterOutLabel = i18n.translate('discover.docViews.table.filterOutValueButtonTooltip', { - defaultMessage: 'Filter out value', - }); - const filterOutAriaLabel = i18n.translate( - 'discover.docViews.table.filterOutValueButtonAriaLabel', - { defaultMessage: 'Filter out value' } - ); - const filtersPairToolTip = - (filtersPairDisabled && - i18n.translate('discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip', { - defaultMessage: 'Unindexed fields or ignored values cannot be searched', - })) || - undefined; - - // Filter exists - const filterExistsLabel = i18n.translate( - 'discover.docViews.table.filterForFieldPresentButtonTooltip', - { defaultMessage: 'Filter for field present' } - ); - const filterExistsAriaLabel = i18n.translate( - 'discover.docViews.table.filterForFieldPresentButtonAriaLabel', - { defaultMessage: 'Filter for field present' } - ); - const filtersExistsDisabled = !fieldMapping || !fieldMapping.filterable; - const filtersExistsToolTip = - (filtersExistsDisabled && - (fieldMapping && fieldMapping.scripted - ? i18n.translate( - 'discover.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', - }))) || - undefined; - - // Toggle columns - const toggleColumnsLabel = i18n.translate( - 'discover.docViews.table.toggleColumnInTableButtonTooltip', - { defaultMessage: 'Toggle column in table' } - ); - const toggleColumnsAriaLabel = i18n.translate( - 'discover.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' }); - const pinnedAriaLabel = pinned - ? i18n.translate('discover.docViews.table.unpinFieldAriaLabel', { - defaultMessage: 'Unpin field', - }) - : i18n.translate('discover.docViews.table.pinFieldAriaLabel', { defaultMessage: 'Pin field' }); - const pinnedIconType = pinned ? 'pinFilled' : 'pin'; - - const toggleOpenPopover = useCallback(() => setIsOpen((current) => !current), []); - const closePopover = useCallback(() => setIsOpen(false), []); - const togglePinned = useCallback(() => onTogglePinned(field), [field, onTogglePinned]); - const onClickAction = useCallback( - (callback: () => void) => () => { - callback(); - closePopover(); - }, - [closePopover] - ); - - const panels = [ - { - id: 0, - title: actionsLabel, - items: [ - { - name: filterAddLabel, - 'aria-label': filterAddAriaLabel, - toolTipContent: filtersPairToolTip, - icon: 'plusInCircle', - disabled: filtersPairDisabled, - 'data-test-subj': `addFilterForValueButton-${field}`, - onClick: onClickAction(onFilter.bind({}, fieldMapping, flattenedField, '+')), - }, - { - name: filterOutLabel, - 'aria-label': filterOutAriaLabel, - toolTipContent: filtersPairToolTip, - icon: 'minusInCircle', - disabled: filtersPairDisabled, - onClick: onClickAction(onFilter.bind({}, fieldMapping, flattenedField, '-')), - }, - { - name: filterExistsLabel, - 'aria-label': filterExistsAriaLabel, - toolTipContent: filtersExistsToolTip, - icon: 'filter', - disabled: filtersExistsDisabled, - 'data-test-subj': `addExistsFilterButton-${field}`, - onClick: onClickAction(onFilter.bind({}, '_exists_', field, '+')), - }, - { - name: toggleColumnsLabel, - 'aria-label': toggleColumnsAriaLabel, - 'data-test-subj': `toggleColumnButton-${field}`, - icon: 'listAdd', - onClick: onClickAction(onToggleColumn.bind({}, field)), - }, - { - name: pinnedLabel, - 'aria-label': pinnedAriaLabel, - icon: pinnedIconType, - onClick: onClickAction(togglePinned), - }, - ], - }, - ]; - - if (mode === 'inline') { - return ( - - {panels[0].items.map((item) => ( - - - - - - ))} - - ); - } - - return ( - - } - isOpen={isOpen} - closePopover={closePopover} - display="block" - panelPaddingSize="none" - > - - - ); -}; diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_value.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_value.tsx deleted file mode 100644 index 85ce340bf568b..0000000000000 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_value.tsx +++ /dev/null @@ -1,137 +0,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 { css } from '@emotion/react'; -import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiTextColor, EuiToolTip } from '@elastic/eui'; -import classNames from 'classnames'; -import React, { Fragment, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { IgnoredReason } from '@kbn/discover-utils'; -import { FieldRecord } from './table'; -import { DocViewTableRowBtnCollapse } from './legacy/table_row_btn_collapse'; - -const COLLAPSE_LINE_LENGTH = 350; - -interface IgnoreWarningProps { - reason: IgnoredReason; - rawValue: unknown; -} - -const IgnoreWarning: React.FC = React.memo(({ rawValue, reason }) => { - const multiValue = Array.isArray(rawValue) && rawValue.length > 1; - - const getToolTipContent = (): string => { - switch (reason) { - case IgnoredReason.IGNORE_ABOVE: - return multiValue - ? i18n.translate('discover.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', { - 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', { - defaultMessage: `This field has one or more malformed values that can't be searched or filtered.`, - }) - : i18n.translate('discover.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', { - 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', { - defaultMessage: `The value in this field was ignored by Elasticsearch and can't be searched or filtered.`, - }); - } - }; - - return ( - - - - - - - - {multiValue - ? i18n.translate('discover.docViews.table.ignored.multiValueLabel', { - defaultMessage: 'Contains ignored values', - }) - : i18n.translate('discover.docViews.table.ignored.singleValueLabel', { - defaultMessage: 'Ignored value', - })} - - - - - ); -}); - -type TableFieldValueProps = Pick & { - formattedValue: FieldRecord['value']['formattedValue']; - rawValue: unknown; - ignoreReason?: IgnoredReason; -}; - -export const TableFieldValue = ({ - formattedValue, - field, - rawValue, - ignoreReason, -}: TableFieldValueProps) => { - const [fieldOpen, setFieldOpen] = useState(false); - - const value = String(rawValue); - const isCollapsible = value.length > COLLAPSE_LINE_LENGTH; - const isCollapsed = isCollapsible && !fieldOpen; - - const valueClassName = classNames({ - // eslint-disable-next-line @typescript-eslint/naming-convention - kbnDocViewer__value: true, - dscTruncateByHeight: isCollapsible && isCollapsed, - }); - - const onToggleCollapse = () => setFieldOpen((fieldOpenPrev) => !fieldOpenPrev); - - return ( - - {(isCollapsible || ignoreReason) && ( - - {isCollapsible && ( - - - - )} - {ignoreReason && ( - - - - )} - - )} -
    - - ); -}; diff --git a/src/plugins/discover/public/services/doc_views/doc_views_types.ts b/src/plugins/discover/public/services/doc_views/doc_views_types.ts deleted file mode 100644 index 4fc94580ba29a..0000000000000 --- a/src/plugins/discover/public/services/doc_views/doc_views_types.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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, DataViewField } from '@kbn/data-views-plugin/public'; -import type { AggregateQuery, Query } from '@kbn/es-query'; -import type { DataTableRecord, IgnoredReason } from '@kbn/discover-utils/types'; - -export interface FieldMapping { - filterable?: boolean; - scripted?: boolean; - rowCount?: number; - type: string; - name: string; - displayName?: string; -} - -export type DocViewFilterFn = ( - mapping: FieldMapping | string | undefined, - value: unknown, - mode: '+' | '-' -) => void; - -export interface DocViewRenderProps { - hit: DataTableRecord; - dataView: DataView; - columns?: string[]; - query?: Query | AggregateQuery; - textBasedHits?: DataTableRecord[]; - filter?: DocViewFilterFn; - onAddColumn?: (columnName: string) => void; - onRemoveColumn?: (columnName: string) => void; -} -export type DocViewerComponent = React.FC; -export type DocViewRenderFn = ( - domeNode: HTMLDivElement, - renderProps: DocViewRenderProps -) => () => void; - -export interface BaseDocViewInput { - order: number; - shouldShow?: (hit: DataTableRecord) => boolean; - title: string; -} - -export interface RenderDocViewInput extends BaseDocViewInput { - render: DocViewRenderFn; - component?: undefined; - directive?: undefined; -} - -interface ComponentDocViewInput extends BaseDocViewInput { - component: DocViewerComponent; - render?: undefined; - directive?: undefined; -} - -export type DocViewInput = ComponentDocViewInput | RenderDocViewInput; - -export type DocView = DocViewInput & { - shouldShow: NonNullable; -}; - -export type DocViewInputFn = () => DocViewInput; - -export interface FieldRecordLegacy { - action: { - isActive: boolean; - onFilter?: DocViewFilterFn; - onToggleColumn: (field: string) => void; - flattenedField: unknown; - }; - field: { - displayName: string; - field: string; - scripted: boolean; - fieldType?: string; - fieldMapping?: DataViewField; - }; - value: { - formattedValue: string; - ignored?: IgnoredReason; - }; -} diff --git a/src/plugins/discover/public/types.ts b/src/plugins/discover/public/types.ts deleted file mode 100644 index 051892902239d..0000000000000 --- a/src/plugins/discover/public/types.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { DatatableColumn } from '@kbn/expressions-plugin/common'; -import type { DataTableRecord } from '@kbn/discover-utils/types'; -import type { SearchResponseInterceptedWarning } from '@kbn/search-response-warnings'; - -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/src/plugins/discover/public/utils/columns.test.ts deleted file mode 100644 index 5ef7d8fea450f..0000000000000 --- a/src/plugins/discover/public/utils/columns.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { getDisplayedColumns } from './columns'; -import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; -import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; - -describe('getDisplayedColumns', () => { - test('returns default columns given a data view without timefield', async () => { - const result = getDisplayedColumns([], dataViewMock); - expect(result).toMatchInlineSnapshot(` - Array [ - "_source", - ] - `); - }); - test('returns default columns given a data view with timefield', async () => { - const result = getDisplayedColumns([], dataViewWithTimefieldMock); - expect(result).toMatchInlineSnapshot(` - Array [ - "_source", - ] - `); - }); - test('returns default columns when just timefield is in state', async () => { - const result = getDisplayedColumns(['timestamp'], dataViewWithTimefieldMock); - expect(result).toMatchInlineSnapshot(` - Array [ - "_source", - ] - `); - }); - test('returns columns given by argument, no fallback ', async () => { - const result = getDisplayedColumns(['test'], dataViewWithTimefieldMock); - expect(result).toMatchInlineSnapshot(` - Array [ - "test", - ] - `); - }); - test('returns the same instance of ["_source"] over multiple calls', async () => { - const result = getDisplayedColumns([], dataViewWithTimefieldMock); - const result2 = getDisplayedColumns([], dataViewWithTimefieldMock); - expect(result).toBe(result2); - }); -}); diff --git a/src/plugins/discover/public/utils/columns.ts b/src/plugins/discover/public/utils/columns.ts deleted file mode 100644 index 49e234b11decc..0000000000000 --- a/src/plugins/discover/public/utils/columns.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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'; - -// 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 -// new columns, and thus performing worse than using the same array over multiple renders. -const SOURCE_ONLY = ['_source']; - -/** - * Function to provide fallback when - * 1) no columns are given - * 2) Just one column is given, which is the configured timefields - */ -export function getDisplayedColumns(stateColumns: string[] = [], dataView: DataView) { - return stateColumns && - stateColumns.length > 0 && - // check if all columns where removed except the configured timeField (this can't be removed) - !(stateColumns.length === 1 && stateColumns[0] === dataView.timeFieldName) - ? stateColumns - : SOURCE_ONLY; -} diff --git a/src/plugins/discover/public/utils/convert_value_to_string.test.tsx b/src/plugins/discover/public/utils/convert_value_to_string.test.tsx deleted file mode 100644 index dd81ad621f182..0000000000000 --- a/src/plugins/discover/public/utils/convert_value_to_string.test.tsx +++ /dev/null @@ -1,585 +0,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 { discoverGridContextComplexMock, discoverGridContextMock } from '../__mocks__/grid_context'; -import { discoverServiceMock } 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, - columnId: 'keyword_key', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('abcd1'); - }); - - it('should convert a text value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'text_message', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('"Hi there! I am a sample string."'); - }); - - it('should convert a text value to text (not for CSV)', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'text_message', - rowIndex: 0, - options: { - compatibleWithCSV: false, - }, - }); - - expect(result.formattedString).toBe('Hi there! I am a sample string.'); - }); - - it('should convert a multiline text value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'text_message', - rowIndex: 1, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('"I\'m multiline\n*&%$#@"'); - expect(result.withFormula).toBe(false); - }); - - it('should convert a number value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'number_price', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('10.99'); - }); - - it('should convert a date value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'date', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('"2022-05-22T12:10:30.000Z"'); - }); - - it('should convert a date nanos value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'date_nanos', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('"2022-01-01T12:10:30.123456789Z"'); - }); - - it('should convert a date nanos value to text (not for CSV)', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'date_nanos', - rowIndex: 0, - options: { - compatibleWithCSV: false, - }, - }); - - expect(result.formattedString).toBe('2022-01-01T12:10:30.123456789Z'); - }); - - it('should convert a boolean value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'bool_enabled', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('false'); - }); - - it('should convert a binary value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'binary_blob', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('"U29tZSBiaW5hcnkgYmxvYg=="'); - }); - - it('should convert a binary value to text (not for CSV)', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'binary_blob', - rowIndex: 0, - options: { - compatibleWithCSV: false, - }, - }); - - expect(result.formattedString).toBe('U29tZSBiaW5hcnkgYmxvYg=='); - }); - - it('should convert an object value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'object_user.first', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('John'); - }); - - it('should convert a nested value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'nested_user', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe( - '{"last":["Smith"],"last.keyword":["Smith"],"first":["John"],"first.keyword":["John"]}, {"last":["White"],"last.keyword":["White"],"first":["Alice"],"first.keyword":["Alice"]}' - ); - }); - - it('should convert a flattened value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'flattened_labels', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('{"release":["v1.2.5","v1.3.0"],"priority":"urgent"}'); - }); - - it('should convert a range value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'range_time_frame', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe( - '{"gte":"2015-10-31 12:00:00","lte":"2015-11-01 00:00:00"}' - ); - }); - - it('should convert a rank features value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'rank_features', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('{"2star":100,"1star":10}'); - }); - - it('should convert a histogram value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'histogram', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('{"counts":[3,7,23,12,6],"values":[0.1,0.2,0.3,0.4,0.5]}'); - }); - - it('should convert a IP value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'ip_addr', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('"192.168.1.1"'); - }); - - it('should convert a IP value to text (not for CSV)', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'ip_addr', - rowIndex: 0, - options: { - compatibleWithCSV: false, - }, - }); - - expect(result.formattedString).toBe('192.168.1.1'); - }); - - it('should convert a version value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'version', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('"1.2.3"'); - }); - - it('should convert a version value to text (not for CSV)', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'version', - rowIndex: 0, - options: { - compatibleWithCSV: false, - }, - }); - - expect(result.formattedString).toBe('1.2.3'); - }); - - it('should convert a vector value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'vector', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('0.5, 10, 6'); - }); - - it('should convert a geo point value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'geo_point', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('{"coordinates":[-71.34,41.12],"type":"Point"}'); - }); - - it('should convert a geo point object value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'geo_point', - rowIndex: 1, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('{"coordinates":[-71.34,41.12],"type":"Point"}'); - }); - - it('should convert an array value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'array_tags', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('elasticsearch, wow'); - }); - - it('should convert a shape value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'geometry', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe( - '{"coordinates":[[[1000,-1001],[1001,-1001],[1001,-1000],[1000,-1000],[1000,-1001]]],"type":"Polygon"}' - ); - }); - - it('should convert a runtime value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'runtime_number', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('5.5'); - }); - - it('should convert a scripted value to text', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'scripted_string', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('"hi there"'); - }); - - it('should convert a scripted value to text (not for CSV)', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'scripted_string', - rowIndex: 0, - options: { - compatibleWithCSV: false, - }, - }); - - expect(result.formattedString).toBe('hi there'); - }); - - it('should return an empty string and not fail', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'unknown', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe(''); - }); - - it('should return an empty string when rowIndex is out of range', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'unknown', - rowIndex: -1, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe(''); - }); - - it('should return _source value', () => { - const result = convertValueToString({ - rows: discoverGridContextMock.rows, - dataView: discoverGridContextMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: '_source', - rowIndex: 0, - options: { - compatibleWithCSV: false, - }, - }); - - expect(result.formattedString).toBe( - '{\n' + - ' "bytes": 20,\n' + - ' "date": "2020-20-01T12:12:12.123",\n' + - ' "message": "test1",\n' + - ' "_index": "i",\n' + - ' "_score": 1\n' + - '}' - ); - }); - - it('should return a formatted _source value', () => { - const result = convertValueToString({ - rows: discoverGridContextMock.rows, - dataView: discoverGridContextMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: '_source', - rowIndex: 0, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe( - '{"bytes":20,"date":"2020-20-01T12:12:12.123","message":"test1","_index":"i","_score":1}' - ); - }); - - it('should escape formula', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'array_tags', - rowIndex: 1, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result.formattedString).toBe('"\'=1+2\'"" ;,=1+2"'); - expect(result.withFormula).toBe(true); - - const result2 = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'scripted_string', - rowIndex: 1, - options: { - compatibleWithCSV: true, - }, - }); - - expect(result2.formattedString).toBe('"\'=1+2"";=1+2"'); - expect(result2.withFormula).toBe(true); - }); - - it('should not escape formulas when not for CSV', () => { - const result = convertValueToString({ - rows: discoverGridContextComplexMock.rows, - dataView: discoverGridContextComplexMock.dataView, - fieldFormats: discoverServiceMock.fieldFormats, - columnId: 'array_tags', - rowIndex: 1, - options: { - compatibleWithCSV: false, - }, - }); - - expect(result.formattedString).toBe('=1+2\'" ;,=1+2'); - expect(result.withFormula).toBe(true); - }); - - it('should return a formatted name', () => { - const result = convertNameToString('test'); - - expect(result.formattedString).toBe('test'); - expect(result.withFormula).toBe(false); - }); - - it('should return a formatted name when with a formula', () => { - const result = convertNameToString('=1+2";=1+2'); - - expect(result.formattedString).toBe('"\'=1+2"";=1+2"'); - expect(result.withFormula).toBe(true); - }); -}); diff --git a/src/plugins/discover/public/utils/row_heights.ts b/src/plugins/discover/public/utils/row_heights.ts deleted file mode 100644 index f1e096b76b9f9..0000000000000 --- a/src/plugins/discover/public/utils/row_heights.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { Storage } from '@kbn/kibana-utils-plugin/public'; -import { isValidRowHeight } from './validate_row_height'; - -export interface DataGridOptionsRecord { - previousRowHeight: number; - previousConfigRowHeight: number; -} - -const ROW_HEIGHT_KEY = 'discover:dataGridRowHeight'; - -export const getStoredRowHeight = (storage: Storage): DataGridOptionsRecord | null => { - const entry = storage.get(ROW_HEIGHT_KEY); - if ( - typeof entry === 'object' && - entry !== null && - isValidRowHeight(entry.previousRowHeight) && - isValidRowHeight(entry.previousConfigRowHeight) - ) { - return entry; - } - return null; -}; - -export const updateStoredRowHeight = ( - newRowHeight: number, - configRowHeight: number, - storage: Storage -) => { - storage.set(ROW_HEIGHT_KEY, { - previousRowHeight: newRowHeight, - previousConfigRowHeight: configRowHeight, - }); -}; diff --git a/src/plugins/discover/public/utils/rows_per_page.test.ts b/src/plugins/discover/public/utils/rows_per_page.test.ts deleted file mode 100644 index 25eddf9a44de2..0000000000000 --- a/src/plugins/discover/public/utils/rows_per_page.test.ts +++ /dev/null @@ -1,42 +0,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 { discoverServiceMock } from '../__mocks__/services'; -import { SAMPLE_ROWS_PER_PAGE_SETTING } from '@kbn/discover-utils'; -import { getRowsPerPageOptions, getDefaultRowsPerPage } from './rows_per_page'; - -const SORTED_OPTIONS = [10, 25, 50, 100, 250, 500]; - -describe('rows per page', () => { - describe('getRowsPerPageOptions', () => { - it('should return default options if not provided', () => { - expect(getRowsPerPageOptions()).toEqual(SORTED_OPTIONS); - }); - - it('should return default options if current value is one of them', () => { - expect(getRowsPerPageOptions(250)).toEqual(SORTED_OPTIONS); - }); - - it('should return extended options if current value is not one of them', () => { - 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/src/plugins/discover/public/utils/rows_per_page.ts deleted file mode 100644 index bc5f07f6253d3..0000000000000 --- a/src/plugins/discover/public/utils/rows_per_page.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. - */ - -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'; - -export const getRowsPerPageOptions = (currentRowsPerPage?: number): number[] => { - return sortBy( - uniq( - typeof currentRowsPerPage === 'number' && currentRowsPerPage > 0 - ? [...ROWS_PER_PAGE_OPTIONS, currentRowsPerPage] - : ROWS_PER_PAGE_OPTIONS - ) - ); -}; - -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/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/embeddable/common/types.ts b/src/plugins/embeddable/common/types.ts index bbf57603d0c9b..85cfc42301f6a 100644 --- a/src/plugins/embeddable/common/types.ts +++ b/src/plugins/embeddable/common/types.ts @@ -22,6 +22,7 @@ export enum ViewMode { } export type EmbeddableInput = { + version?: string; viewMode?: ViewMode; title?: string; description?: string; @@ -72,7 +73,9 @@ export type EmbeddableInput = { executionContext?: KibanaExecutionContext; }; -export interface PanelState { +export interface PanelState< + E extends EmbeddableInput & { id: string } = { id: string; version?: string } +> { // The type of embeddable in this panel. Will be used to find the factory in which to // load the embeddable. type: string; @@ -80,9 +83,6 @@ export interface PanelState & { id: string }; - - // allows individual embeddable panels to maintain versioning information separate from the main Kibana version - version?: string; } export type EmbeddableStateWithType = EmbeddableInput & { type: string }; diff --git a/src/plugins/embeddable/public/index.ts b/src/plugins/embeddable/public/index.ts index 42244c70ed9c6..91e6efcdc41c8 100644 --- a/src/plugins/embeddable/public/index.ts +++ b/src/plugins/embeddable/public/index.ts @@ -80,6 +80,7 @@ export { shouldRefreshFilterCompareOptions, PANEL_HOVER_TRIGGER, panelHoverTrigger, + runEmbeddableFactoryMigrations, } from './lib'; export { EmbeddablePanel } from './embeddable_panel'; diff --git a/src/plugins/embeddable/public/lib/containers/container.ts b/src/plugins/embeddable/public/lib/containers/container.ts index a53cfb8725fac..fceae56cf4b96 100644 --- a/src/plugins/embeddable/public/lib/containers/container.ts +++ b/src/plugins/embeddable/public/lib/containers/container.ts @@ -37,8 +37,8 @@ import { PanelState, EmbeddableContainerSettings, } from './i_container'; -import { PanelNotFoundError, EmbeddableFactoryNotFoundError } from '../errors'; import { EmbeddableStart } from '../../plugin'; +import { PanelNotFoundError, EmbeddableFactoryNotFoundError } from '../errors'; import { isSavedObjectEmbeddableInput } from '../../../common/lib/saved_object_embeddable'; const getKeys = (o: T): Array => Object.keys(o) as Array; @@ -345,6 +345,7 @@ export abstract class Container< explicitInput: { ...explicitInput, id: embeddableId, + version: factory.latestVersion, } as TEmbeddableInput, }; } @@ -491,6 +492,7 @@ export abstract class Container< } else if (embeddable === undefined) { this.removeEmbeddable(panel.explicitInput.id); } + return embeddable; } diff --git a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts index e7b8893848c93..472840208e139 100644 --- a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts +++ b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts @@ -7,11 +7,13 @@ */ import { SavedObjectAttributes } from '@kbn/core/public'; -import { EmbeddableFactoryDefinition } from './embeddable_factory_definition'; -import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable'; + +import { IContainer } from '..'; import { EmbeddableFactory } from './embeddable_factory'; import { EmbeddableStateWithType } from '../../../common/types'; -import { IContainer } from '..'; +import { EmbeddableFactoryDefinition } from './embeddable_factory_definition'; +import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable'; +import { runEmbeddableFactoryMigrations } from '../factory_migrations/run_factory_migrations'; export const defaultEmbeddableFactoryProvider = < I extends EmbeddableInput = EmbeddableInput, @@ -21,7 +23,14 @@ export const defaultEmbeddableFactoryProvider = < >( def: EmbeddableFactoryDefinition ): EmbeddableFactory => { + if (def.migrations && !def.latestVersion) { + throw new Error( + 'To run clientside Embeddable migrations a latest version key is required on the factory' + ); + } + const factory: EmbeddableFactory = { + latestVersion: def.latestVersion, isContainerType: def.isContainerType ?? false, canCreateNew: def.canCreateNew ? def.canCreateNew.bind(def) : () => true, getDefaultInput: def.getDefaultInput ? def.getDefaultInput.bind(def) : () => ({}), @@ -33,7 +42,12 @@ export const defaultEmbeddableFactoryProvider = < : (savedObjectId: string, input: Partial, parent?: IContainer) => { throw new Error(`Creation from saved object not supported by type ${def.type}`); }, - create: def.create.bind(def), + create: (...args) => { + const [initialInput, ...otherArgs] = args; + const { input } = runEmbeddableFactoryMigrations(initialInput, def); + const createdEmbeddable = def.create.bind(def)(input as I, ...otherArgs); + return createdEmbeddable; + }, type: def.type, isEditable: def.isEditable.bind(def), getDisplayName: def.getDisplayName.bind(def), diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx index 695c23fa0a2e2..d145bfb3c1ae0 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx @@ -94,7 +94,6 @@ export abstract class Embeddable< this.onResetInput(newInput); }); } - this.getOutput$() .pipe( map(({ title }) => title || ''), diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts index 0d4aa5f150abc..8f6b51ec41b23 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts @@ -36,6 +36,14 @@ export interface EmbeddableFactory< >, TSavedObjectAttributes = unknown > extends PersistableState { + /** + * The version of this Embeddable factory. This will be used in the client side migration system + * to ensure that input from any source is compatible with the latest version of this embeddable. + * If the latest version is not defined, all clientside migrations will be skipped. If migrations + * are added to this factory but a latestVersion is not set, an error will be thrown on server start + */ + readonly latestVersion?: string; + // A unique identified for this factory, which will be used to map an embeddable spec to // a factory that can generate an instance of it. readonly type: string; @@ -115,10 +123,8 @@ export interface EmbeddableFactory< ): Promise; /** - * Resolves to undefined if a new Embeddable cannot be directly created and the user will instead be redirected - * elsewhere. - * - * This will likely change in future iterations when we improve in place editing capabilities. + * Creates an Embeddable instance, running the inital input through all registered migrations. Resolves to undefined if a new Embeddable + * cannot be directly created and the user will instead be redirected elsewhere. */ create( initialInput: TEmbeddableInput, diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts index 06f3a268c9ae5..4c360ffd40eb5 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts @@ -17,7 +17,10 @@ export type EmbeddableFactoryDefinition< T = unknown > = // Required parameters - Pick, 'create' | 'type' | 'isEditable' | 'getDisplayName'> & + Pick< + EmbeddableFactory, + 'create' | 'type' | 'latestVersion' | 'isEditable' | 'getDisplayName' + > & // Optional parameters Partial< Pick< diff --git a/src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.test.ts b/src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.test.ts new file mode 100644 index 0000000000000..291950d1fa988 --- /dev/null +++ b/src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.test.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { EmbeddableInput } from '../embeddables'; +import { runEmbeddableFactoryMigrations } from './run_factory_migrations'; + +describe('Run embeddable factory migrations', () => { + interface TestInputTypeVersion009 extends EmbeddableInput { + version: '0.0.9'; + keyThatAlwaysExists: string; + keyThatGetsRemoved: string; + } + interface TestInputTypeVersion100 extends EmbeddableInput { + version: '1.0.0'; + id: string; + keyThatAlwaysExists: string; + keyThatGetsAdded: string; + } + + const migrations = { + '1.0.0': (input: TestInputTypeVersion009): TestInputTypeVersion100 => { + const newInput: TestInputTypeVersion100 = { + id: input.id, + version: '1.0.0', + keyThatAlwaysExists: input.keyThatAlwaysExists, + keyThatGetsAdded: 'I just got born', + }; + return newInput; + }, + }; + + it('should return the initial input and migrationRun=false if the current version is the latest', () => { + const initialInput: TestInputTypeVersion100 = { + id: 'superId', + version: '1.0.0', + keyThatAlwaysExists: 'Inside Problems', + keyThatGetsAdded: 'Oh my - I just got born', + }; + + const factory = { + latestVersion: '1.0.0', + migrations, + }; + + const result = runEmbeddableFactoryMigrations(initialInput, factory); + + expect(result.input).toBe(initialInput); + expect(result.migrationRun).toBe(false); + }); + + it('should return migrated input and migrationRun=true if version does not match latestVersion', () => { + const initialInput: TestInputTypeVersion009 = { + id: 'superId', + version: '0.0.9', + keyThatAlwaysExists: 'Inside Problems', + keyThatGetsRemoved: 'juvenile plumage', + }; + + const factory = { + latestVersion: '1.0.0', + migrations, + }; + + const result = runEmbeddableFactoryMigrations(initialInput, factory); + + expect(result.migrationRun).toBe(true); + expect(result.input.version).toBe('1.0.0'); + expect((result.input as unknown as TestInputTypeVersion009).keyThatGetsRemoved).toBeUndefined(); + expect(result.input.keyThatGetsAdded).toEqual('I just got born'); + }); +}); diff --git a/src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.ts b/src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.ts new file mode 100644 index 0000000000000..9bd49eec331e7 --- /dev/null +++ b/src/plugins/embeddable/public/lib/factory_migrations/run_factory_migrations.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 { cloneDeep } from 'lodash'; +import compare from 'semver/functions/compare'; + +import { migrateToLatest } from '@kbn/kibana-utils-plugin/common'; +import { EmbeddableFactory, EmbeddableInput } from '../embeddables'; + +/** + * A helper function that migrates an Embeddable Input to its latest version. Note that this function + * only runs the embeddable factory's migrations. + */ +export const runEmbeddableFactoryMigrations = ( + initialInput: { version?: string }, + factory: { migrations?: EmbeddableFactory['migrations']; latestVersion?: string } +): { input: ToType; migrationRun: boolean } => { + if (!factory.latestVersion) { + return { input: initialInput as unknown as ToType, migrationRun: false }; + } + + // any embeddable with no version set is considered to require all clientside migrations so we default to 0.0.0 + const inputVersion = initialInput.version ?? '0.0.0'; + const migrationRun = compare(inputVersion, factory.latestVersion, true) !== 0; + + // return early to avoid extra operations when there are no migrations to run. + if (!migrationRun) return { input: initialInput as unknown as ToType, migrationRun }; + + const factoryMigrations = + typeof factory?.migrations === 'function' ? factory?.migrations() : factory?.migrations || {}; + const migratedInput = migrateToLatest( + factoryMigrations ?? {}, + { + state: cloneDeep(initialInput), + version: inputVersion, + }, + true + ); + migratedInput.version = factory.latestVersion; + return { input: migratedInput as ToType, migrationRun }; +}; diff --git a/src/plugins/embeddable/public/lib/index.ts b/src/plugins/embeddable/public/lib/index.ts index ad25c74ca3ba9..ecf37a506befc 100644 --- a/src/plugins/embeddable/public/lib/index.ts +++ b/src/plugins/embeddable/public/lib/index.ts @@ -15,3 +15,4 @@ export * from './state_transfer'; export * from './reference_or_value_embeddable'; export * from './self_styled_embeddable'; export * from './filterable_embeddable'; +export * from './factory_migrations/run_factory_migrations'; diff --git a/src/plugins/embeddable/public/plugin.test.ts b/src/plugins/embeddable/public/plugin.test.ts index 82d9801503536..743b672bbf588 100644 --- a/src/plugins/embeddable/public/plugin.test.ts +++ b/src/plugins/embeddable/public/plugin.test.ts @@ -25,6 +25,7 @@ test('can set custom embeddable factory provider', async () => { setup.setCustomEmbeddableFactoryProvider(customProvider); setup.registerEmbeddableFactory('test', { type: 'test', + latestVersion: '1.0.0', create: () => Promise.resolve(undefined), getDisplayName: () => 'Test', isEditable: () => Promise.resolve(true), @@ -66,6 +67,7 @@ test('custom embeddable factory provider test for intercepting embeddable creati setup.setCustomEmbeddableFactoryProvider(customProvider); setup.registerEmbeddableFactory('test', { type: 'test', + latestVersion: '1.0.0', create: (input, parent) => Promise.resolve(new HelloWorldEmbeddable(input, parent)), getDisplayName: () => 'Test', isEditable: () => Promise.resolve(true), @@ -98,6 +100,7 @@ describe('embeddable factory', () => { extract: jest.fn().mockImplementation((state) => ({ state, references: [] })), inject: jest.fn().mockImplementation((state) => state), telemetry: jest.fn().mockResolvedValue({}), + latestVersion: '7.11.0', migrations: { '7.11.0': jest.fn().mockImplementation((state) => state) }, } as any; const embeddableState = { @@ -109,6 +112,7 @@ describe('embeddable factory', () => { const containerEmbeddableFactoryId = 'CONTAINER'; const containerEmbeddableFactory = { type: containerEmbeddableFactoryId, + latestVersion: '1.0.0', create: jest.fn(), getDisplayName: () => 'Container', isContainer: true, diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/not_authorized_section.tsx b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/not_authorized_section.tsx index f896826eca6d5..0a81102d6a515 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/not_authorized_section.tsx +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/not_authorized_section.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { EuiEmptyPrompt } from '@elastic/eui'; +import { EuiPageTemplate } from '@elastic/eui'; interface Props { title: React.ReactNode; @@ -16,7 +16,7 @@ interface Props { } export const NotAuthorizedSection = ({ title, message, dataTestSubj }: Props) => ( - {title}

    } diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/page_error.tsx b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/page_error.tsx index 0d2e5a7f8f635..274e98525145f 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/page_error.tsx +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/page_error.tsx @@ -6,11 +6,7 @@ * Side Public License, v 1. */ -import { - EuiSpacer, - EuiEmptyPrompt, - EuiPageContent_Deprecated as EuiPageContent, -} from '@elastic/eui'; +import { EuiSpacer, EuiPageTemplate } from '@elastic/eui'; import React from 'react'; import { APP_WRAPPER_CLASS } from '@kbn/core/public'; import { Error } from '../types'; @@ -41,35 +37,34 @@ export const PageError: React.FunctionComponent = ({ const message = error?.message; const errorContent = ( - - {title}

    } - body={ - error && ( - <> - {cause ? ( - message || errorString - ) : ( -

    {message || errorString}

    - )} - {cause && ( - <> - -
      - {cause.map((causeMsg, i) => ( -
    • {causeMsg}
    • - ))} -
    - - )} - - ) - } - iconType="warning" - actions={actions} - {...rest} - /> - + {title}} + body={ + error && ( + <> + {cause ? ( + message || errorString + ) : ( +

    {message || errorString}

    + )} + {cause && ( + <> + +
      + {cause.map((causeMsg, i) => ( +
    • {causeMsg}
    • + ))} +
    + + )} + + ) + } + iconType="warning" + color="danger" + actions={actions} + {...rest} + /> ); if (isCentered) { diff --git a/src/plugins/es_ui_shared/public/components/page_loading/page_loading.tsx b/src/plugins/es_ui_shared/public/components/page_loading/page_loading.tsx index 38caa1d817720..bac5d85842900 100644 --- a/src/plugins/es_ui_shared/public/components/page_loading/page_loading.tsx +++ b/src/plugins/es_ui_shared/public/components/page_loading/page_loading.tsx @@ -7,21 +7,14 @@ */ import React from 'react'; -import { - EuiEmptyPrompt, - EuiLoadingSpinner, - EuiText, - EuiPageContent_Deprecated as EuiPageContent, -} from '@elastic/eui'; +import { EuiLoadingSpinner, EuiText, EuiPageTemplate } from '@elastic/eui'; export const PageLoading: React.FunctionComponent = ({ children }) => { return ( - - } - body={{children}} - data-test-subj="sectionLoading" - /> - + } + body={{children}} + data-test-subj="sectionLoading" + /> ); }; 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/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts index d8932f234e39a..593e437fd9dc7 100644 --- a/src/plugins/expressions/common/execution/execution.ts +++ b/src/plugins/expressions/common/execution/execution.ts @@ -420,18 +420,20 @@ export class Execution< : of(resolvedArgs); return args$.pipe( - tap((args) => this.execution.params.debug && Object.assign(head.debug, { args })), + tap((args) => this.execution.params.debug && Object.assign(head.debug ?? {}, { args })), switchMap((args) => this.invokeFunction(fn, input, args)), this.execution.params.partial ? identity : last(), switchMap((output) => (getType(output) === 'error' ? throwError(output) : of(output))), - tap((output) => this.execution.params.debug && Object.assign(head.debug, { output })), + tap( + (output) => this.execution.params.debug && Object.assign(head.debug ?? {}, { output }) + ), switchMap((output) => this.invokeChain(tail, output)), catchError((rawError) => { const error = createError(rawError); error.error.message = `[${fnName}] > ${error.error.message}`; if (this.execution.params.debug) { - Object.assign(head.debug, { error, rawError, success: false }); + Object.assign(head.debug ?? {}, { error, rawError, success: false }); } return of(error); @@ -440,7 +442,7 @@ export class Execution< }), finalize(() => { if (this.execution.params.debug) { - Object.assign(head.debug, { duration: now() - timeStart }); + Object.assign(head.debug ?? {}, { duration: now() - timeStart }); } }) ); diff --git a/src/plugins/expressions/common/expression_functions/expression_function_parameter.ts b/src/plugins/expressions/common/expression_functions/expression_function_parameter.ts index 530d0bc5a9c5c..644eb4bb8005e 100644 --- a/src/plugins/expressions/common/expression_functions/expression_function_parameter.ts +++ b/src/plugins/expressions/common/expression_functions/expression_function_parameter.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { KnownTypeToString } from '../types'; +import { TypeString } from '../types'; import { ArgumentType } from './arguments'; export class ExpressionFunctionParameter { @@ -46,6 +46,6 @@ export class ExpressionFunctionParameter { } accepts(type: string) { - return !this.types?.length || this.types.includes(type as KnownTypeToString); + return !this.types?.length || this.types.includes(type as TypeString); } } 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/field_formats/common/converters/duration.test.ts b/src/plugins/field_formats/common/converters/duration.test.ts index 58e3fb4f3a967..52fb64888f5ac 100644 --- a/src/plugins/field_formats/common/converters/duration.test.ts +++ b/src/plugins/field_formats/common/converters/duration.test.ts @@ -15,6 +15,10 @@ describe('Duration Format', () => { outputPrecision: undefined, showSuffix: undefined, fixtures: [ + { + input: 0, + output: '0 seconds', + }, { input: -60, output: 'minus a minute', diff --git a/src/plugins/field_formats/common/converters/duration.ts b/src/plugins/field_formats/common/converters/duration.ts index 1579d6058e98c..1ed6ec014ed47 100644 --- a/src/plugins/field_formats/common/converters/duration.ts +++ b/src/plugins/field_formats/common/converters/duration.ts @@ -99,6 +99,12 @@ export class DurationFormat extends FieldFormat { const human = this.isHuman(); const humanPrecise = this.isHumanPrecise(); + if (human && val === 0) { + return i18n.translate('fieldFormats.duration.zeroSecondsLabel', { + defaultMessage: '0 seconds', + }); // Handle the case of 0 value for "Human Friendly" + } + const prefix = val < 0 && human ? i18n.translate('fieldFormats.duration.negativeLabel', { 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/home/public/application/application.tsx b/src/plugins/home/public/application/application.tsx index f3a7146343d91..1c28ff0b8fcee 100644 --- a/src/plugins/home/public/application/application.tsx +++ b/src/plugins/home/public/application/application.tsx @@ -32,7 +32,7 @@ export const renderApp = async ( ) => { const { featureCatalogue, chrome, dataViewsService: dataViews, trackUiMetric } = getServices(); - // all the directories could be get in "start" phase of plugin after all of the legacy plugins will be moved to a NP + // FIXME: use featureCatalogue.getFeatures$() const directories = featureCatalogue.get(); // Filters solutions by available nav links diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts index a728d6721faee..49d6b42dd7dea 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts @@ -7,6 +7,7 @@ */ import type { PublicMethodsOf } from '@kbn/utility-types'; +import * as Rx from 'rxjs'; import { FeatureCatalogueRegistrySetup, FeatureCatalogueRegistry, @@ -25,6 +26,7 @@ const createMock = (): jest.Mocked> => setup: jest.fn(), start: jest.fn(), get: jest.fn(() => []), + getFeatures$: jest.fn(() => Rx.of([])), getSolutions: jest.fn(() => []), removeFeature: jest.fn(), }; diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts index 759ff5e3d0d23..81b7297f3b62f 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts @@ -6,9 +6,10 @@ * Side Public License, v 1. */ +import { firstValueFrom } from 'rxjs'; import { - FeatureCatalogueRegistry, FeatureCatalogueEntry, + FeatureCatalogueRegistry, FeatureCatalogueSolution, } from './feature_catalogue_registry'; @@ -49,45 +50,57 @@ describe('FeatureCatalogueRegistry', () => { `"Solution with id [kibana] has already been registered. Use a unique id."` ); }); + + test('throws when getting features before start()', async () => { + const getFeaturesBeforeStart = async () => { + const service = new FeatureCatalogueRegistry(); + const catalogue = service.setup(); + catalogue.register(DASHBOARD_FEATURE); + await firstValueFrom(service.getFeatures$()); + }; + expect(getFeaturesBeforeStart).rejects.toEqual( + new Error(`Catalogue entries are only available after start phase`) + ); + }); }); describe('start', () => { describe('capabilities filtering', () => { - test('retains items with no entry in capabilities', () => { + test('retains items with no entry in capabilities', async () => { const service = new FeatureCatalogueRegistry(); service.setup().register(DASHBOARD_FEATURE); const capabilities = { catalogue: {} } as any; service.start({ capabilities }); - expect(service.get()).toEqual([DASHBOARD_FEATURE]); + expect(await firstValueFrom(service.getFeatures$())).toEqual([DASHBOARD_FEATURE]); }); - test('retains items with true in capabilities', () => { + test('retains items with true in capabilities', async () => { const service = new FeatureCatalogueRegistry(); service.setup().register(DASHBOARD_FEATURE); const capabilities = { catalogue: { dashboard: true } } as any; service.start({ capabilities }); - expect(service.get()).toEqual([DASHBOARD_FEATURE]); + expect(await firstValueFrom(service.getFeatures$())).toEqual([DASHBOARD_FEATURE]); }); - test('removes items with false in capabilities', () => { + test('removes items with false in capabilities', async () => { const service = new FeatureCatalogueRegistry(); service.setup().register(DASHBOARD_FEATURE); const capabilities = { catalogue: { dashboard: false } } as any; service.start({ capabilities }); - expect(service.get()).toEqual([]); + expect(await firstValueFrom(service.getFeatures$())).toEqual([]); }); }); describe('visibility filtering', () => { - test('retains items with no "visible" callback', () => { + test('retains items with no "visible" callback', async () => { const service = new FeatureCatalogueRegistry(); service.setup().register(DASHBOARD_FEATURE); const capabilities = { catalogue: {} } as any; service.start({ capabilities }); - expect(service.get()).toEqual([DASHBOARD_FEATURE]); + expect(await firstValueFrom(service.getFeatures$())).toEqual([DASHBOARD_FEATURE]); }); - test('retains items with a "visible" callback which returns "true"', () => { + test('retains items with a "visible" callback which returns "true"', async () => { const service = new FeatureCatalogueRegistry(); const feature = { ...DASHBOARD_FEATURE, @@ -96,10 +109,10 @@ describe('FeatureCatalogueRegistry', () => { service.setup().register(feature); const capabilities = { catalogue: {} } as any; service.start({ capabilities }); - expect(service.get()).toEqual([feature]); + expect(await firstValueFrom(service.getFeatures$())).toEqual([feature]); }); - test('removes items with a "visible" callback which returns "false"', () => { + test('removes items with a "visible" callback which returns "false"', async () => { const service = new FeatureCatalogueRegistry(); const feature = { ...DASHBOARD_FEATURE, @@ -108,13 +121,44 @@ describe('FeatureCatalogueRegistry', () => { service.setup().register(feature); const capabilities = { catalogue: {} } as any; service.start({ capabilities }); - expect(service.get()).toEqual([]); + expect(await firstValueFrom(service.getFeatures$())).toEqual([]); }); }); }); + describe('reactivity', () => { + const DASHBOARD_FEATURE_2: FeatureCatalogueEntry = { + ...DASHBOARD_FEATURE, + id: 'dashboard_2', + }; + + test('addition of catalogue entry after start()', async () => { + const service = new FeatureCatalogueRegistry(); + const catalogue = service.setup(); + const capabilities = { catalogue: { dashboard: true } } as any; + service.start({ capabilities }); + catalogue.register(DASHBOARD_FEATURE); + catalogue.register(DASHBOARD_FEATURE_2); + expect(await firstValueFrom(service.getFeatures$())).toEqual([ + DASHBOARD_FEATURE, + DASHBOARD_FEATURE_2, + ]); + }); + + test('removal of catalogue entry after start()', async () => { + const service = new FeatureCatalogueRegistry(); + const catalogue = service.setup(); + catalogue.register(DASHBOARD_FEATURE); + catalogue.register(DASHBOARD_FEATURE_2); + const capabilities = { catalogue: { dashboard: true } } as any; + service.start({ capabilities }); + service.removeFeature('dashboard'); + expect(await firstValueFrom(service.getFeatures$())).toEqual([DASHBOARD_FEATURE_2]); + }); + }); + describe('title sorting', () => { - test('sorts by title ascending', () => { + test('sorts by title ascending', async () => { const service = new FeatureCatalogueRegistry(); const setup = service.setup(); setup.register({ id: '1', title: 'Orange' } as any); @@ -122,7 +166,7 @@ describe('FeatureCatalogueRegistry', () => { setup.register({ id: '3', title: 'Banana' } as any); const capabilities = { catalogue: {} } as any; service.start({ capabilities }); - expect(service.get()).toEqual([ + expect(await firstValueFrom(service.getFeatures$())).toEqual([ { id: '2', title: 'Apple' }, { id: '3', title: 'Banana' }, { id: '1', title: 'Orange' }, diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts index 2bc84b44f5540..3d22f6156a966 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts @@ -8,6 +8,7 @@ import { Capabilities } from '@kbn/core/public'; import { IconType } from '@elastic/eui'; +import { BehaviorSubject, map, Observable } from 'rxjs'; /** @public */ export type FeatureCatalogueCategory = 'admin' | 'data' | 'other'; @@ -56,19 +57,21 @@ export interface FeatureCatalogueSolution { export class FeatureCatalogueRegistry { private capabilities: Capabilities | null = null; - private readonly features = new Map(); - private readonly solutions = new Map(); + private solutions = new Map(); + private featuresSubject = new BehaviorSubject>(new Map()); public setup() { return { register: (feature: FeatureCatalogueEntry) => { - if (this.features.has(feature.id)) { + const { value: features } = this.featuresSubject; + if (features.has(feature.id)) { throw new Error( `Feature with id [${feature.id}] has already been registered. Use a unique id.` ); } - this.features.set(feature.id, feature); + features.set(feature.id, feature); + this.featuresSubject.next(new Map(features)); }, registerSolution: (solution: FeatureCatalogueSolution) => { if (this.solutions.has(solution.id)) { @@ -86,12 +89,16 @@ export class FeatureCatalogueRegistry { this.capabilities = capabilities; } - public get(): FeatureCatalogueEntry[] { + /** + * @deprecated + * Use getFeatures$() instead + */ + public get(features = this.featuresSubject.value): FeatureCatalogueEntry[] { if (this.capabilities === null) { throw new Error('Catalogue entries are only available after start phase'); } const capabilities = this.capabilities; - return [...this.features.values()] + return [...features.values()] .filter( (entry) => capabilities.catalogue[entry.id] !== false && (entry.visible ? entry.visible() : true) @@ -99,6 +106,10 @@ export class FeatureCatalogueRegistry { .sort(compareByKey('title')); } + public getFeatures$(): Observable { + return this.featuresSubject.pipe(map((feats) => this.get(feats))); + } + public getSolutions(): FeatureCatalogueSolution[] { if (this.capabilities === null) { throw new Error('Catalogue entries are only available after start phase'); @@ -110,7 +121,9 @@ export class FeatureCatalogueRegistry { } public removeFeature(appId: string) { - this.features.delete(appId); + const { value: features } = this.featuresSubject; + features.delete(appId); + this.featuresSubject.next(new Map(features)); } } 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_overview/public/application.tsx b/src/plugins/kibana_overview/public/application.tsx index 03ad03876a132..d0a0be8ab653e 100644 --- a/src/plugins/kibana_overview/public/application.tsx +++ b/src/plugins/kibana_overview/public/application.tsx @@ -24,7 +24,7 @@ export const renderApp = ( const { notifications, http } = core; const { newsfeed, home, navigation } = deps; const newsfeed$ = newsfeed?.createNewsFeed$(NewsfeedApiEndpoint.KIBANA_ANALYTICS); - const features = home.featureCatalogue.get(); + const features$ = home.featureCatalogue.getFeatures$(); core.chrome.setBreadcrumbs([ { text: i18n.translate('kibanaOverview.breadcrumbs.title', { defaultMessage: 'Analytics' }) }, @@ -42,7 +42,7 @@ export const renderApp = ( diff --git a/src/plugins/kibana_overview/public/components/app.tsx b/src/plugins/kibana_overview/public/components/app.tsx index c8c9834f8b562..7d79cc5cb7bc6 100644 --- a/src/plugins/kibana_overview/public/components/app.tsx +++ b/src/plugins/kibana_overview/public/components/app.tsx @@ -6,15 +6,16 @@ * Side Public License, v 1. */ -import React, { useEffect, useState } from 'react'; -import { Observable } from 'rxjs'; +import type { CoreStart } from '@kbn/core/public'; +import type { FeatureCatalogueEntry, FeatureCatalogueSolution } from '@kbn/home-plugin/public'; import { I18nProvider } from '@kbn/i18n-react'; -import { HashRouter as Router } from 'react-router-dom'; +import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public'; +import type { FetchResult } from '@kbn/newsfeed-plugin/public'; import { Route, Routes } from '@kbn/shared-ux-router'; -import { CoreStart } from '@kbn/core/public'; -import { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public'; -import { FetchResult } from '@kbn/newsfeed-plugin/public'; -import { FeatureCatalogueEntry, FeatureCatalogueSolution } from '@kbn/home-plugin/public'; +import React, { useEffect, useState } from 'react'; +import { HashRouter as Router } from 'react-router-dom'; +import useObservable from 'react-use/lib/useObservable'; +import type { Observable } from 'rxjs'; import { Overview } from './overview'; interface KibanaOverviewAppDeps { @@ -23,16 +24,17 @@ interface KibanaOverviewAppDeps { http: CoreStart['http']; navigation: NavigationPublicPluginStart; newsfeed$?: Observable; + features$: Observable; solutions: FeatureCatalogueSolution[]; - features: FeatureCatalogueEntry[]; } export const KibanaOverviewApp = ({ basename, newsfeed$, + features$, solutions, - features, }: KibanaOverviewAppDeps) => { + const features = useObservable(features$, []); const [newsFetchResult, setNewsFetchResult] = useState(null); useEffect(() => { 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/kibana_utils/common/persistable_state/migrate_to_latest.ts b/src/plugins/kibana_utils/common/persistable_state/migrate_to_latest.ts index 98d1f6da2918f..75b8b25bf3f79 100644 --- a/src/plugins/kibana_utils/common/persistable_state/migrate_to_latest.ts +++ b/src/plugins/kibana_utils/common/persistable_state/migrate_to_latest.ts @@ -12,10 +12,11 @@ import { VersionedState, MigrateFunctionsObject } from './types'; export function migrateToLatest( migrations: MigrateFunctionsObject, - { state, version: oldVersion }: VersionedState + { state, version: oldVersion }: VersionedState, + loose?: boolean ): S { const versions = Object.keys(migrations || {}) - .filter((v) => compare(v, oldVersion) > 0) + .filter((v) => compare(v, oldVersion, loose) > 0) .sort(compare); if (!versions.length) return state as S; diff --git a/src/plugins/kibana_utils/common/persistable_state/types.ts b/src/plugins/kibana_utils/common/persistable_state/types.ts index 31234ca5c18da..c8c0a3a344732 100644 --- a/src/plugins/kibana_utils/common/persistable_state/types.ts +++ b/src/plugins/kibana_utils/common/persistable_state/types.ts @@ -78,9 +78,9 @@ export interface PersistableState

    ; 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/saved_search/common/service/saved_searches_utils.test.ts b/src/plugins/saved_search/common/service/saved_searches_utils.test.ts index 8286276bb898e..67f368637d3f5 100644 --- a/src/plugins/saved_search/common/service/saved_searches_utils.test.ts +++ b/src/plugins/saved_search/common/service/saved_searches_utils.test.ts @@ -60,6 +60,7 @@ describe('saved_searches_utils', () => { }, "getConfig": [MockFunction], "onResponse": [MockFunction], + "scriptedFieldsEnabled": true, "search": [MockFunction], }, "fields": Object {}, 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/telemetry/server/routes/telemetry_usage_stats.ts b/src/plugins/telemetry/server/routes/telemetry_usage_stats.ts index a828de911c29a..a2cee086ee563 100644 --- a/src/plugins/telemetry/server/routes/telemetry_usage_stats.ts +++ b/src/plugins/telemetry/server/routes/telemetry_usage_stats.ts @@ -92,6 +92,7 @@ export function registerTelemetryUsageStatsRoutes( .post({ access: 'internal', path: FetchSnapshotTelemetry, + enableQueryVersion: true, // Allow specifying the version through querystring so that we can use it in Dev Console }) // Just because it used to be /v2/, we are creating identical v1 and v2. .addVersion({ version: '1', 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 89% 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 45dbe65ba8f81..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( {' '} @@ -127,7 +130,6 @@ describe('DocViewTable at Discover', () => { { _property: '_index', addInclusiveFilterButton: true, - collapseBtn: false, noMappingWarning: false, toggleColumnButton: true, underscoreWarning: false, @@ -135,7 +137,6 @@ describe('DocViewTable at Discover', () => { { _property: 'message', addInclusiveFilterButton: false, - collapseBtn: true, noMappingWarning: false, toggleColumnButton: true, underscoreWarning: false, @@ -143,7 +144,6 @@ describe('DocViewTable at Discover', () => { { _property: '_underscore', addInclusiveFilterButton: false, - collapseBtn: false, noMappingWarning: false, toggleColumnButton: true, underScoreWarning: true, @@ -151,7 +151,6 @@ describe('DocViewTable at Discover', () => { { _property: 'scripted', addInclusiveFilterButton: false, - collapseBtn: false, noMappingWarning: false, toggleColumnButton: true, underScoreWarning: false, @@ -159,7 +158,6 @@ describe('DocViewTable at Discover', () => { { _property: 'not_mapped', addInclusiveFilterButton: false, - collapseBtn: false, noMappingWarning: true, toggleColumnButton: true, underScoreWarning: false, @@ -171,26 +169,21 @@ describe('DocViewTable at Discover', () => { expect(rowComponent.length).toBe(1); }); - ( - [ - 'addInclusiveFilterButton', - 'collapseBtn', - 'toggleColumnButton', - 'underscoreWarning', - ] as const - ).forEach((element) => { - const elementExist = check[element]; - - if (typeof elementExist === 'boolean') { - const btn = findTestSubject(rowComponent, element, '^='); - - it(`renders ${element} for '${check._property}' correctly`, () => { - const disabled = btn.length ? btn.props().disabled : true; - const clickAble = btn.length && !disabled ? true : false; - expect(clickAble).toBe(elementExist); - }); + (['addInclusiveFilterButton', 'toggleColumnButton', 'underscoreWarning'] as const).forEach( + (element) => { + const elementExist = check[element]; + + if (typeof elementExist === 'boolean') { + const btn = findTestSubject(rowComponent, element, '^='); + + it(`renders ${element} for '${check._property}' correctly`, () => { + const disabled = btn.length ? btn.props().disabled : true; + const clickAble = btn.length && !disabled ? true : false; + expect(clickAble).toBe(elementExist); + }); + } } - }); + ); }); }); @@ -236,17 +229,6 @@ describe('DocViewTable at Discover Context', () => { btn.simulate('click'); expect(props.filter).toBeCalled(); }); - - it(`renders functional collapse button`, () => { - const btn = findTestSubject(component, `collapseBtn`); - const html = component.html(); - - expect(component.html()).toContain('dscTruncateByHeight'); - - expect(btn.length).toBe(1); - btn.simulate('click'); - expect(component.html() !== html).toBeTruthy(); - }); }); describe('DocViewTable at Discover Doc', () => { @@ -440,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/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx new file mode 100644 index 0000000000000..6b2a70b868911 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table.tsx @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 '../table.scss'; +import React, { useCallback, useMemo } from 'react'; +import { EuiInMemoryTable } from '@elastic/eui'; +import { getFieldIconType } from '@kbn/unified-field-list/src/utils/field_types/get_field_icon_type'; +import { + SHOW_MULTIFIELDS, + formatFieldValue, + getIgnoredReason, + getShouldShowFieldHandler, + isNestedFieldParent, +} from '@kbn/discover-utils'; +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 = ({ + columns, + hit, + dataView, + filter, + onAddColumn, + onRemoveColumn, +}: DocViewRenderProps) => { + const { fieldFormats, uiSettings } = useUnifiedDocViewerServices(); + const showMultiFields = useMemo(() => uiSettings.get(SHOW_MULTIFIELDS), [uiSettings]); + + const mapping = useCallback((name: string) => dataView.fields.getByName(name), [dataView.fields]); + const tableColumns = useMemo(() => { + return filter ? [ACTIONS_COLUMN, ...MAIN_COLUMNS] : MAIN_COLUMNS; + }, [filter]); + const onToggleColumn = useCallback( + (field: string) => { + if (!onRemoveColumn || !onAddColumn || !columns) { + return; + } + if (columns.includes(field)) { + onRemoveColumn(field); + } else { + onAddColumn(field); + } + }, + [onRemoveColumn, onAddColumn, columns] + ); + + const onSetRowProps = useCallback(({ field: { field } }: FieldRecordLegacy) => { + return { + key: field, + className: 'kbnDocViewer__tableRow', + 'data-test-subj': `tableDocViewRow-${field}`, + }; + }, []); + + const shouldShowFieldHandler = useMemo( + () => getShouldShowFieldHandler(Object.keys(hit.flattened), dataView, showMultiFields), + [hit.flattened, dataView, showMultiFields] + ); + + const items: FieldRecordLegacy[] = Object.keys(hit.flattened) + .filter(shouldShowFieldHandler) + .sort((fieldA, fieldB) => { + const mappingA = mapping(fieldA); + const mappingB = mapping(fieldB); + const nameA = !mappingA || !mappingA.displayName ? fieldA : mappingA.displayName; + const nameB = !mappingB || !mappingB.displayName ? fieldB : mappingB.displayName; + return nameA.localeCompare(nameB); + }) + .map((field) => { + const fieldMapping = mapping(field); + const displayName = fieldMapping?.displayName ?? field; + const fieldType = isNestedFieldParent(field, dataView) + ? 'nested' + : fieldMapping + ? getFieldIconType(fieldMapping) + : undefined; + const ignored = getIgnoredReason(fieldMapping ?? field, hit.raw._ignored); + return { + action: { + onToggleColumn, + onFilter: filter, + isActive: !!columns?.includes(field), + flattenedField: hit.flattened[field], + }, + field: { + field, + displayName, + fieldMapping, + fieldType, + scripted: Boolean(fieldMapping?.scripted), + }, + value: { + formattedValue: formatFieldValue( + hit.flattened[field], + hit.raw, + fieldFormats, + dataView, + fieldMapping + ), + ignored, + }, + }; + }); + + return ( + + ); +}; diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx new file mode 100644 index 0000000000000..4499a44190747 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/legacy/table_cell_actions.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +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'; + +interface TableActionsProps { + field: string; + isActive: boolean; + flattenedField: unknown; + fieldMapping?: DataViewField; + onFilter: DocViewFilterFn; + onToggleColumn: (field: string) => void; + ignoredValue: boolean; +} + +export const TableActions = ({ + isActive, + field, + fieldMapping, + flattenedField, + onToggleColumn, + onFilter, + ignoredValue, +}: TableActionsProps) => { + return ( +
    + onFilter(fieldMapping, flattenedField, '+')} + /> + onFilter(fieldMapping, flattenedField, '-')} + /> + onToggleColumn(field)} + /> + onFilter('_exists_', field, '+')} + scripted={fieldMapping && fieldMapping.scripted} + /> +
    + ); +}; 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 ( void; + fieldname: string; +} + +export function DocViewTableRowBtnToggleColumn({ + onClick, + active, + disabled = false, + fieldname = '', +}: Props) { + if (disabled) { + return ( + + ); + } + return ( + + } + > + + + ); +} diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.scss b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table.scss similarity index 100% rename from src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.scss rename to src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table.scss diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table.tsx new file mode 100644 index 0000000000000..6d679ff688c7f --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table.tsx @@ -0,0 +1,443 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 './table.scss'; +import React, { useCallback, useMemo, useState } from 'react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiFieldSearch, + EuiSpacer, + EuiTable, + EuiTableBody, + EuiTableRowCell, + EuiTableRow, + EuiTableHeader, + EuiTableHeaderCell, + EuiText, + EuiTablePagination, + EuiSelectableMessage, + EuiI18n, + useIsWithinBreakpoints, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { debounce } from 'lodash'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { getFieldIconType } from '@kbn/unified-field-list/src/utils/field_types/get_field_icon_type'; +import { + SHOW_MULTIFIELDS, + formatFieldValue, + getIgnoredReason, + getShouldShowFieldHandler, + isNestedFieldParent, + usePager, +} from '@kbn/discover-utils'; +import type { DocViewRenderProps, FieldRecordLegacy } from '@kbn/unified-doc-viewer/types'; +import { FieldName } from '@kbn/unified-doc-viewer'; +import { useUnifiedDocViewerServices } from '../../hooks'; +import { TableFieldValue } from './table_cell_value'; +import { TableActions } from './table_cell_actions'; + +export interface FieldRecord { + action: Omit; + field: { + pinned: boolean; + onTogglePinned: (field: string) => void; + } & FieldRecordLegacy['field']; + value: FieldRecordLegacy['value']; +} + +interface ItemsEntry { + pinnedItems: FieldRecord[]; + restItems: FieldRecord[]; +} + +const MOBILE_OPTIONS = { header: false }; +const PAGE_SIZE_OPTIONS = [25, 50, 100]; +const DEFAULT_PAGE_SIZE = 25; +const PINNED_FIELDS_KEY = 'discover:pinnedFields'; +const PAGE_SIZE = 'discover:pageSize'; +const SEARCH_TEXT = 'discover:searchText'; + +const getPinnedFields = (dataViewId: string, storage: Storage): string[] => { + const pinnedFieldsEntry = storage.get(PINNED_FIELDS_KEY); + if ( + typeof pinnedFieldsEntry === 'object' && + pinnedFieldsEntry !== null && + Array.isArray(pinnedFieldsEntry[dataViewId]) + ) { + return pinnedFieldsEntry[dataViewId].filter((cur: unknown) => typeof cur === 'string'); + } + return []; +}; +const updatePinnedFieldsState = (newFields: string[], dataViewId: string, storage: Storage) => { + let pinnedFieldsEntry = storage.get(PINNED_FIELDS_KEY); + pinnedFieldsEntry = + typeof pinnedFieldsEntry === 'object' && pinnedFieldsEntry !== null ? pinnedFieldsEntry : {}; + + storage.set(PINNED_FIELDS_KEY, { + ...pinnedFieldsEntry, + [dataViewId]: newFields, + }); +}; + +const getPageSize = (storage: Storage): number => { + const pageSize = Number(storage.get(PAGE_SIZE)); + return pageSize && PAGE_SIZE_OPTIONS.includes(pageSize) ? pageSize : DEFAULT_PAGE_SIZE; +}; +const updatePageSize = (newPageSize: number, storage: Storage) => { + storage.set(PAGE_SIZE, newPageSize); +}; + +const getSearchText = (storage: Storage) => { + return storage.get(SEARCH_TEXT) || ''; +}; +const updateSearchText = debounce( + (newSearchText: string, storage: Storage) => storage.set(SEARCH_TEXT, newSearchText), + 500 +); + +export const DocViewerTable = ({ + columns, + hit, + dataView, + filter, + onAddColumn, + onRemoveColumn, +}: DocViewRenderProps) => { + const showActionsInsideTableCell = useIsWithinBreakpoints(['xl'], true); + + const { fieldFormats, storage, uiSettings } = useUnifiedDocViewerServices(); + const showMultiFields = uiSettings.get(SHOW_MULTIFIELDS); + const currentDataViewId = dataView.id!; + const isSingleDocView = !filter; + + const [searchText, setSearchText] = useState(getSearchText(storage)); + const [pinnedFields, setPinnedFields] = useState( + getPinnedFields(currentDataViewId, storage) + ); + + const flattened = hit.flattened; + const shouldShowFieldHandler = useMemo( + () => getShouldShowFieldHandler(Object.keys(flattened), dataView, showMultiFields), + [flattened, dataView, showMultiFields] + ); + + const searchPlaceholder = i18n.translate('unifiedDocViewer.docView.table.searchPlaceHolder', { + defaultMessage: 'Search field names', + }); + + const mapping = useCallback((name: string) => dataView.fields.getByName(name), [dataView.fields]); + + const onToggleColumn = useCallback( + (field: string) => { + if (!onRemoveColumn || !onAddColumn || !columns) { + return; + } + if (columns.includes(field)) { + onRemoveColumn(field); + } else { + onAddColumn(field); + } + }, + [onRemoveColumn, onAddColumn, columns] + ); + + const onTogglePinned = useCallback( + (field: string) => { + const newPinned = pinnedFields.includes(field) + ? pinnedFields.filter((curField) => curField !== field) + : [...pinnedFields, field]; + + updatePinnedFieldsState(newPinned, currentDataViewId, storage); + setPinnedFields(newPinned); + }, + [currentDataViewId, pinnedFields, storage] + ); + + const fieldToItem = useCallback( + (field: string) => { + const fieldMapping = mapping(field); + const displayName = fieldMapping?.displayName ?? field; + const fieldType = isNestedFieldParent(field, dataView) + ? 'nested' + : fieldMapping + ? getFieldIconType(fieldMapping) + : undefined; + + const ignored = getIgnoredReason(fieldMapping ?? field, hit.raw._ignored); + + return { + action: { + onToggleColumn, + onFilter: filter, + isActive: !!columns?.includes(field), + flattenedField: flattened[field], + }, + field: { + field, + displayName, + fieldMapping, + fieldType, + scripted: Boolean(fieldMapping?.scripted), + pinned: pinnedFields.includes(displayName), + onTogglePinned, + }, + value: { + formattedValue: formatFieldValue( + hit.flattened[field], + hit.raw, + fieldFormats, + dataView, + fieldMapping + ), + ignored, + }, + }; + }, + [ + mapping, + dataView, + hit, + onToggleColumn, + filter, + columns, + flattened, + pinnedFields, + onTogglePinned, + fieldFormats, + ] + ); + + const handleOnChange = useCallback( + (event: React.ChangeEvent) => { + const newSearchText = event.currentTarget.value; + updateSearchText(newSearchText, storage); + setSearchText(newSearchText); + }, + [storage] + ); + + const { pinnedItems, restItems } = Object.keys(flattened) + .sort((fieldA, fieldB) => { + const mappingA = mapping(fieldA); + const mappingB = mapping(fieldB); + const nameA = !mappingA || !mappingA.displayName ? fieldA : mappingA.displayName; + const nameB = !mappingB || !mappingB.displayName ? fieldB : mappingB.displayName; + return nameA.localeCompare(nameB); + }) + .reduce( + (acc, curFieldName) => { + if (!shouldShowFieldHandler(curFieldName)) { + return acc; + } + + if (pinnedFields.includes(curFieldName)) { + acc.pinnedItems.push(fieldToItem(curFieldName)); + } else { + const fieldMapping = mapping(curFieldName); + const displayName = fieldMapping?.displayName ?? curFieldName; + if (displayName.toLowerCase().includes(searchText.toLowerCase())) { + // filter only unpinned fields + acc.restItems.push(fieldToItem(curFieldName)); + } + } + + return acc; + }, + { + pinnedItems: [], + restItems: [], + } + ); + + const { curPageIndex, pageSize, totalPages, startIndex, changePageIndex, changePageSize } = + usePager({ + initialPageSize: getPageSize(storage), + totalItems: restItems.length, + }); + const showPagination = totalPages !== 0; + + const onChangePageSize = useCallback( + (newPageSize: number) => { + updatePageSize(newPageSize, storage); + changePageSize(newPageSize); + }, + [changePageSize, storage] + ); + + const headers = [ + !isSingleDocView && ( + + + + + + + + ), + + + + + + + , + + + + + + + , + ]; + + const renderRows = useCallback( + (items: FieldRecord[]) => { + const highlight = searchText?.toLowerCase(); + return items.map( + ({ + action: { flattenedField, onFilter }, + field: { field, fieldMapping, fieldType, scripted, pinned }, + value: { formattedValue, ignored }, + }: FieldRecord) => { + return ( + + {!isSingleDocView && ( + + + + )} + + + + + + + + ); + } + ); + }, + [onToggleColumn, onTogglePinned, isSingleDocView, showActionsInsideTableCell, searchText] + ); + + const rowElements = [ + ...renderRows(pinnedItems), + ...renderRows(restItems.slice(startIndex, pageSize + startIndex)), + ]; + + return ( + + + + + + + + + + {rowElements.length === 0 ? ( + +

    + +

    +
    + ) : ( + + + {headers} + {rowElements} + + + )} + + + + + + {showPagination && ( + + + + )} +
    + ); +}; diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx new file mode 100644 index 0000000000000..8b9a35e071310 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_actions.tsx @@ -0,0 +1,241 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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, { useCallback, useState } from 'react'; +import { + EuiButtonIcon, + EuiContextMenu, + EuiPopover, + EuiFlexGroup, + EuiFlexItem, + EuiToolTip, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import type { DataViewField } from '@kbn/data-views-plugin/public'; +import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; + +interface TableActionsProps { + mode?: 'inline' | 'as_popover'; + field: string; + pinned: boolean; + flattenedField: unknown; + fieldMapping?: DataViewField; + onFilter: DocViewFilterFn; + onToggleColumn: (field: string) => void; + ignoredValue: boolean; + onTogglePinned: (field: string) => void; +} + +export const TableActions = ({ + mode = 'as_popover', + pinned, + field, + fieldMapping, + flattenedField, + onToggleColumn, + onFilter, + ignoredValue, + onTogglePinned, +}: TableActionsProps) => { + const [isOpen, setIsOpen] = useState(false); + const openActionsLabel = i18n.translate('unifiedDocViewer.docView.table.actions.open', { + defaultMessage: 'Open actions', + }); + const actionsLabel = i18n.translate('unifiedDocViewer.docView.table.actions.label', { + defaultMessage: 'Actions', + }); + + // Filters pair + const filtersPairDisabled = !fieldMapping || !fieldMapping.filterable || ignoredValue; + const filterAddLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.filterForValueButtonTooltip', + { + defaultMessage: 'Filter for value', + } + ); + const filterAddAriaLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.filterForValueButtonAriaLabel', + { defaultMessage: 'Filter for value' } + ); + const filterOutLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.filterOutValueButtonTooltip', + { + defaultMessage: 'Filter out value', + } + ); + const filterOutAriaLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.filterOutValueButtonAriaLabel', + { defaultMessage: 'Filter out value' } + ); + const filtersPairToolTip = + (filtersPairDisabled && + i18n.translate('unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip', { + defaultMessage: 'Unindexed fields or ignored values cannot be searched', + })) || + undefined; + + // Filter exists + const filterExistsLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.filterForFieldPresentButtonTooltip', + { defaultMessage: 'Filter for field present' } + ); + const filterExistsAriaLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.filterForFieldPresentButtonAriaLabel', + { defaultMessage: 'Filter for field present' } + ); + const filtersExistsDisabled = !fieldMapping || !fieldMapping.filterable; + const filtersExistsToolTip = + (filtersExistsDisabled && + (fieldMapping && fieldMapping.scripted + ? i18n.translate( + 'unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip', + { + defaultMessage: 'Unable to filter for presence of scripted fields', + } + ) + : i18n.translate( + 'unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip', + { + defaultMessage: 'Unable to filter for presence of meta fields', + } + ))) || + undefined; + + // Toggle columns + const toggleColumnsLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.toggleColumnInTableButtonTooltip', + { defaultMessage: 'Toggle column in table' } + ); + const toggleColumnsAriaLabel = i18n.translate( + 'unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel', + { defaultMessage: 'Toggle column in table' } + ); + + // Pinned + const pinnedLabel = pinned + ? i18n.translate('unifiedDocViewer.docViews.table.unpinFieldLabel', { + defaultMessage: 'Unpin field', + }) + : i18n.translate('unifiedDocViewer.docViews.table.pinFieldLabel', { + defaultMessage: 'Pin field', + }); + const pinnedAriaLabel = pinned + ? i18n.translate('unifiedDocViewer.docViews.table.unpinFieldAriaLabel', { + defaultMessage: 'Unpin field', + }) + : i18n.translate('unifiedDocViewer.docViews.table.pinFieldAriaLabel', { + defaultMessage: 'Pin field', + }); + const pinnedIconType = pinned ? 'pinFilled' : 'pin'; + + const toggleOpenPopover = useCallback(() => setIsOpen((current) => !current), []); + const closePopover = useCallback(() => setIsOpen(false), []); + const togglePinned = useCallback(() => onTogglePinned(field), [field, onTogglePinned]); + const onClickAction = useCallback( + (callback: () => void) => () => { + callback(); + closePopover(); + }, + [closePopover] + ); + + const panels = [ + { + id: 0, + title: actionsLabel, + items: [ + { + name: filterAddLabel, + 'aria-label': filterAddAriaLabel, + toolTipContent: filtersPairToolTip, + icon: 'plusInCircle', + disabled: filtersPairDisabled, + 'data-test-subj': `addFilterForValueButton-${field}`, + onClick: onClickAction(onFilter.bind({}, fieldMapping, flattenedField, '+')), + }, + { + name: filterOutLabel, + 'aria-label': filterOutAriaLabel, + toolTipContent: filtersPairToolTip, + icon: 'minusInCircle', + disabled: filtersPairDisabled, + onClick: onClickAction(onFilter.bind({}, fieldMapping, flattenedField, '-')), + }, + { + name: filterExistsLabel, + 'aria-label': filterExistsAriaLabel, + toolTipContent: filtersExistsToolTip, + icon: 'filter', + disabled: filtersExistsDisabled, + 'data-test-subj': `addExistsFilterButton-${field}`, + onClick: onClickAction(onFilter.bind({}, '_exists_', field, '+')), + }, + { + name: toggleColumnsLabel, + 'aria-label': toggleColumnsAriaLabel, + 'data-test-subj': `toggleColumnButton-${field}`, + icon: 'listAdd', + onClick: onClickAction(onToggleColumn.bind({}, field)), + }, + { + name: pinnedLabel, + 'aria-label': pinnedAriaLabel, + icon: pinnedIconType, + onClick: onClickAction(togglePinned), + }, + ], + }, + ]; + + if (mode === 'inline') { + return ( + + {panels[0].items.map((item) => ( + + + + + + ))} + + ); + } + + return ( + + } + isOpen={isOpen} + closePopover={closePopover} + display="block" + panelPaddingSize="none" + > + + + ); +}; diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx new file mode 100644 index 0000000000000..79c79e6a45836 --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table_cell_value.tsx @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { css } from '@emotion/react'; +import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiTextColor, EuiToolTip } from '@elastic/eui'; +import classNames from 'classnames'; +import React, { Fragment } from 'react'; +import { i18n } from '@kbn/i18n'; +import { IgnoredReason } from '@kbn/discover-utils'; +import { FieldRecord } from './table'; + +interface IgnoreWarningProps { + reason: IgnoredReason; + rawValue: unknown; +} + +const IgnoreWarning: React.FC = React.memo(({ rawValue, reason }) => { + const multiValue = Array.isArray(rawValue) && rawValue.length > 1; + + const getToolTipContent = (): string => { + switch (reason) { + case IgnoredReason.IGNORE_ABOVE: + return multiValue + ? 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('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('unifiedDocViewer.docView.table.ignored.multiMalformedTooltip', { + defaultMessage: `This field has one or more malformed values that can't be searched or filtered.`, + }) + : 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('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('unifiedDocViewer.docView.table.ignored.singleUnknownTooltip', { + defaultMessage: `The value in this field was ignored by Elasticsearch and can't be searched or filtered.`, + }); + } + }; + + return ( + + + + + + + + {multiValue + ? i18n.translate('unifiedDocViewer.docViews.table.ignored.multiValueLabel', { + defaultMessage: 'Contains ignored values', + }) + : i18n.translate('unifiedDocViewer.docViews.table.ignored.singleValueLabel', { + defaultMessage: 'Ignored value', + })} + + + + + ); +}); + +type TableFieldValueProps = Pick & { + formattedValue: FieldRecord['value']['formattedValue']; + rawValue: unknown; + ignoreReason?: IgnoredReason; +}; + +export const TableFieldValue = ({ + formattedValue, + field, + rawValue, + ignoreReason, +}: TableFieldValueProps) => { + const valueClassName = classNames({ + // eslint-disable-next-line @typescript-eslint/naming-convention + kbnDocViewer__value: true, + }); + return ( + + {ignoreReason && ( + + {ignoreReason && ( + + + + )} + + )} +
    + + ); +}; 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/unified_doc_viewer/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 new file mode 100644 index 0000000000000..fa5dbfbe616ea --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/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/kibana-react-plugin/public'; + +const codeEditorAriaLabel = i18n.translate('unifiedDocViewer.json.codeEditorAriaLabel', { + defaultMessage: 'Read only JSON view of an elasticsearch document', +}); +const copyToClipboardLabel = i18n.translate('unifiedDocViewer.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/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_histogram/public/panels/panels_resizable.tsx b/src/plugins/unified_histogram/public/panels/panels_resizable.tsx index 36af60f317247..773ebe172b25e 100644 --- a/src/plugins/unified_histogram/public/panels/panels_resizable.tsx +++ b/src/plugins/unified_histogram/public/panels/panels_resizable.tsx @@ -61,7 +61,7 @@ export const PanelsResizable = ({ [] ); const resizeWithPortalsHackButtonCss = css` - z-index: 3 !important; // !important can be removed once EuiResizableButton is converted to Emotion + z-index: 3; `; const resizeWithPortalsHackOverlayCss = css` position: absolute; @@ -164,12 +164,8 @@ export const PanelsResizable = ({ const { euiTheme } = useEuiTheme(); const buttonCss = css` - // The selectors here are intended to override EuiResizableButtons's Sass styles - // it can be removed once EuiResizableButton has been converted to Emotion - &.euiResizableButton.euiResizableButton--vertical { - margin-top: -${euiTheme.size.base}; - margin-bottom: 0; - } + margin-top: -${euiTheme.size.base}; + margin-bottom: 0; `; return ( 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_menu.test.tsx b/src/plugins/unified_search/public/query_string_input/query_bar_menu.test.tsx index d5c6377d20942..bdab607b2030c 100644 --- a/src/plugins/unified_search/public/query_string_input/query_bar_menu.test.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_bar_menu.test.tsx @@ -247,6 +247,7 @@ describe('Querybar Menu component', () => { }, filters: [], }, + namespaces: ['default'], }, }; const component = mount(wrapQueryBarMenuComponentInContext(newProps, 'kuery')); 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/saved_query_management/saved_query_management_list.test.tsx b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.test.tsx index c891174986510..3dbdfaf7588fc 100644 --- a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.test.tsx +++ b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.test.tsx @@ -77,6 +77,7 @@ describe('Saved query management list component', () => { }, filters: [], }, + namespaces: ['default'], }, ]), deleteSavedQuery: jest.fn(), @@ -157,6 +158,38 @@ describe('Saved query management list component', () => { await flushEffect(component); findTestSubject(component, 'delete-saved-query-Test-button').simulate('click'); expect(component.find('[data-test-subj="confirmModalConfirmButton"]').length).toBeTruthy(); + expect(component.text()).not.toContain('you remove it from every space'); + }); + + it('should render the modal with warning for multiple namespaces on delete', async () => { + const newProps = { + ...props, + savedQueryService: { + ...props.savedQueryService, + getAllSavedQueries: jest.fn().mockResolvedValue([ + { + id: '8a0b7cd0-b0c4-11ec-92b2-73d62e0d28a9', + attributes: { + title: 'Test', + description: '', + query: { + query: 'category.keyword : "Men\'s Shoes" ', + language: 'kuery', + }, + filters: [], + }, + namespaces: ['one', 'two'], + }, + ]), + deleteSavedQuery: jest.fn(), + }, + }; + const component = mount(wrapSavedQueriesListComponentInContext(newProps)); + await flushEffect(component); + findTestSubject(component, 'delete-saved-query-Test-button').simulate('click'); + + expect(component.find('[data-test-subj="confirmModalConfirmButton"]').length).toBeTruthy(); + expect(component.text()).toContain('you remove it from every space'); }); it('should render the onClearSavedQuery on delete of the current selected query', async () => { @@ -174,6 +207,7 @@ describe('Saved query management list component', () => { }, filters: [], }, + namespaces: ['default'], }, onClearSavedQuery: onClearSavedQuerySpy, }; diff --git a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx index 5ebb89bd88afc..0cff3baa90883 100644 --- a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx +++ b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx @@ -199,6 +199,13 @@ export function SavedQueryManagementList({ ' ' + savedQueryDescriptionText; + const savedQueryMultipleNamespacesDeleteWarning = i18n.translate( + 'unifiedSearch.search.searchBar.savedQueryMultipleNamespacesDeleteWarning', + { + defaultMessage: `This saved query is shared in multiple spaces. When you delete it, you remove it from every space it is shared in. You can't undo this action.`, + } + ); + const savedQueriesOptions = () => { const savedQueriesWithoutCurrent = savedQueries.filter((savedQuery) => { if (!loadedSavedQuery) return true; @@ -379,7 +386,12 @@ export function SavedQueryManagementList({ onCancel={() => { setShowDeletionConfirmationModal(false); }} - /> + > + {toBeDeletedSavedQuery.namespaces.length > 1 || + toBeDeletedSavedQuery.namespaces.includes('*') + ? savedQueryMultipleNamespacesDeleteWarning + : null} + )} ); 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/lib/populate_state_from_saved_query.test.ts b/src/plugins/unified_search/public/search_bar/lib/populate_state_from_saved_query.test.ts index e401d98a1f7ab..11c879ee33ecb 100644 --- a/src/plugins/unified_search/public/search_bar/lib/populate_state_from_saved_query.test.ts +++ b/src/plugins/unified_search/public/search_bar/lib/populate_state_from_saved_query.test.ts @@ -25,6 +25,7 @@ describe('populateStateFromSavedQuery', () => { language: 'kuery', }, }, + namespaces: ['default'], }; beforeEach(() => { 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/usage_collection/server/routes/stats/stats.ts b/src/plugins/usage_collection/server/routes/stats/stats.ts index 8c32003f38098..6e4a606216035 100644 --- a/src/plugins/usage_collection/server/routes/stats/stats.ts +++ b/src/plugins/usage_collection/server/routes/stats/stats.ts @@ -55,7 +55,10 @@ export function registerStatsRoute({ path: '/api/stats', options: { authRequired: !config.allowAnonymous, - tags: ['api'], // ensures that unauthenticated calls receive a 401 rather than a 302 redirect to login page + // The `api` tag ensures that unauthenticated calls receive a 401 rather than a 302 redirect to login page. + // The `security:acceptJWT` tag allows route to be accessed with JWT credentials. It points to + // ROUTE_TAG_ACCEPT_JWT from '@kbn/security-plugin/server' that cannot be imported here directly. + tags: ['api', 'security:acceptJWT'], access: 'public', // needs to be public to allow access from "system" users like metricbeat. }, validate: { diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx index 2c7f394f6a0aa..3310df7259df6 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx @@ -13,7 +13,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { SelectOption, SwitchOption } from '@kbn/vis-default-editor-plugin/public'; -import { Labels } from '@kbn/charts-plugin/public'; +import type { LabelRotation, Labels } from '@kbn/charts-plugin/public'; import { TruncateLabelsOption } from '../../common'; import { getRotateOptions } from '../../../collections'; @@ -34,7 +34,8 @@ function LabelOptions({ }: LabelOptionsProps) { const setAxisLabelRotate = useCallback( (paramName: 'rotate', value: Labels['rotate']) => { - setAxisLabel(paramName, Number(value)); + const rotation = Number(value) as LabelRotation; + setAxisLabel(paramName, rotation); }, [setAxisLabel] ); @@ -96,6 +97,7 @@ function LabelOptions({ options={rotateOptions} paramName="rotate" value={axisLabels.rotate} + // @ts-ignore ts upgrade v4.7.4 setValue={setAxisLabelRotate} /> 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/fields_for_wildcard_route/conflicts.ts b/test/api_integration/apis/data_views/fields_for_wildcard_route/conflicts.ts index d21b03ef8a7cc..2c1347d97496b 100644 --- a/test/api_integration/apis/data_views/fields_for_wildcard_route/conflicts.ts +++ b/test/api_integration/apis/data_views/fields_for_wildcard_route/conflicts.ts @@ -45,7 +45,7 @@ export default function ({ getService }: FtrProviderContext) { { name: 'number_conflict', type: 'number', - esTypes: ['integer', 'float'], + esTypes: ['float', 'integer'], aggregatable: true, searchable: true, readFromDocValues: true, @@ -54,16 +54,16 @@ export default function ({ getService }: FtrProviderContext) { { name: 'string_conflict', type: 'string', - esTypes: ['text', 'keyword'], + esTypes: ['keyword', 'text'], aggregatable: true, searchable: true, - readFromDocValues: false, + readFromDocValues: true, metadata_field: false, }, { name: 'success', type: 'conflict', - esTypes: ['boolean', 'keyword'], + esTypes: ['keyword', 'boolean'], aggregatable: true, searchable: true, readFromDocValues: false, 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/home/sample_data.ts b/test/api_integration/apis/home/sample_data.ts index 32f20ad6d10e2..b26fe638e1224 100644 --- a/test/api_integration/apis/home/sample_data.ts +++ b/test/api_integration/apis/home/sample_data.ts @@ -25,7 +25,8 @@ export default function ({ getService }: FtrProviderContext) { return appLinks.some((item) => item.path === path); }; - describe('sample data apis', () => { + // Failing: See https://github.com/elastic/kibana/issues/164568 + describe.skip('sample data apis', () => { before(async () => { await esArchiver.emptyKibanaIndex(); }); diff --git a/test/api_integration/apis/index.ts b/test/api_integration/apis/index.ts index 89d97bba330ae..c132970084df1 100644 --- a/test/api_integration/apis/index.ts +++ b/test/api_integration/apis/index.ts @@ -21,6 +21,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./kql_telemetry')); loadTestFile(require.resolve('./saved_objects_management')); loadTestFile(require.resolve('./saved_objects')); + loadTestFile(require.resolve('./saved_queries')); loadTestFile(require.resolve('./scripts')); loadTestFile(require.resolve('./search')); loadTestFile(require.resolve('./short_url')); diff --git a/test/api_integration/apis/saved_objects/delete_unknown_types.ts b/test/api_integration/apis/saved_objects/delete_unknown_types.ts index 225d45fb11b7f..f361199a8fdfa 100644 --- a/test/api_integration/apis/saved_objects/delete_unknown_types.ts +++ b/test/api_integration/apis/saved_objects/delete_unknown_types.ts @@ -54,40 +54,23 @@ export default function ({ getService }: FtrProviderContext) { it('should return 200 with individual responses', async () => { const beforeDelete = await fetchIndexContent(); - expect(beforeDelete).to.eql([ - { - id: 'dashboard:b70c7ae0-3224-11e8-a572-ffca06da1357', - type: 'dashboard', - }, - { - id: 'index-pattern:8963ca30-3224-11e8-a572-ffca06da1357', - type: 'index-pattern', - }, - { - id: 'search:960372e0-3224-11e8-a572-ffca06da1357', - type: 'search', - }, - { - id: 'space:default', - type: 'space', - }, - { - id: 'unknown-shareable-doc', - type: 'unknown-shareable-type', - }, - { - id: 'unknown-type:unknown-doc', - type: 'unknown-type', - }, - { - id: 'visualization:a42c0580-3224-11e8-a572-ffca06da1357', - type: 'visualization', - }, - ]); + const beforeDeleteIds = beforeDelete.map((obj) => obj.id); + [ + 'dashboard:b70c7ae0-3224-11e8-a572-ffca06da1357', + 'index-pattern:8963ca30-3224-11e8-a572-ffca06da1357', + 'search:960372e0-3224-11e8-a572-ffca06da1357', + 'space:default', + 'unknown-shareable-doc', + 'unknown-type:unknown-doc', + 'visualization:a42c0580-3224-11e8-a572-ffca06da1357', + ].forEach((id) => { + expect(beforeDeleteIds).to.contain(id); + }); await supertest .post(`/internal/saved_objects/deprecations/_delete_unknown_types`) .send({}) + .set('kbn-xsrf', 'true') .expect(200) .then((resp) => { expect(resp.body).to.eql({ success: true }); @@ -101,28 +84,15 @@ export default function ({ getService }: FtrProviderContext) { await delay(1000); continue; } - expect(afterDelete).to.eql([ - { - id: 'dashboard:b70c7ae0-3224-11e8-a572-ffca06da1357', - type: 'dashboard', - }, - { - id: 'index-pattern:8963ca30-3224-11e8-a572-ffca06da1357', - type: 'index-pattern', - }, - { - id: 'search:960372e0-3224-11e8-a572-ffca06da1357', - type: 'search', - }, - { - id: 'space:default', - type: 'space', - }, - { - id: 'visualization:a42c0580-3224-11e8-a572-ffca06da1357', - type: 'visualization', - }, - ]); + const afterDeleteIds = afterDelete.map((obj) => obj.id); + [ + 'dashboard:b70c7ae0-3224-11e8-a572-ffca06da1357', + 'index-pattern:8963ca30-3224-11e8-a572-ffca06da1357', + 'search:960372e0-3224-11e8-a572-ffca06da1357', + 'space:default', + 'visualization:a42c0580-3224-11e8-a572-ffca06da1357', + ].forEach((id) => expect(afterDeleteIds).to.contain(id)); + break; } }); diff --git a/test/api_integration/apis/saved_queries/index.js b/test/api_integration/apis/saved_queries/index.js new file mode 100644 index 0000000000000..6f531e8026940 --- /dev/null +++ b/test/api_integration/apis/saved_queries/index.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. + */ + +export default function ({ loadTestFile }) { + describe('Saved queries', () => { + loadTestFile(require.resolve('./saved_queries')); + }); +} diff --git a/test/api_integration/apis/saved_queries/saved_queries.js b/test/api_integration/apis/saved_queries/saved_queries.js new file mode 100644 index 0000000000000..eb3c1465e24de --- /dev/null +++ b/test/api_integration/apis/saved_queries/saved_queries.js @@ -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 expect from '@kbn/expect'; +import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import { SAVED_QUERY_BASE_URL } from '@kbn/data-plugin/common'; + +// node scripts/functional_tests --config test/api_integration/config.js --grep="search session" + +const mockSavedQuery = { + title: 'my title', + description: 'my description', + query: { + query: 'foo: bar', + language: 'kql', + }, + filters: [], +}; + +export default function ({ getService }) { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + void SAVED_QUERY_BASE_URL; + + describe('Saved queries API', function () { + before(async () => { + await esArchiver.emptyKibanaIndex(); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + }); + + after(async () => { + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + }); + + it('should return 200 for create saved query', () => + supertest + .post(`${SAVED_QUERY_BASE_URL}/_create`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send(mockSavedQuery) + .expect(200) + .then(({ body }) => { + expect(body.id).to.have.length(36); + expect(body.attributes.title).to.be('my title'); + expect(body.attributes.description).to.be('my description'); + })); + + it('should return 400 for create invalid saved query', () => + supertest + .post(`${SAVED_QUERY_BASE_URL}/_create`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send({ description: 'my description' }) + .expect(400)); + + it('should return 200 for update saved query', () => + supertest + .post(`${SAVED_QUERY_BASE_URL}/_create`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send(mockSavedQuery) + .expect(200) + .then(({ body }) => + supertest + .put(`${SAVED_QUERY_BASE_URL}/${body.id}`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send({ + ...mockSavedQuery, + title: 'my new title', + }) + .expect(200) + .then((res) => { + expect(res.body.id).to.be(body.id); + expect(res.body.attributes.title).to.be('my new title'); + }) + )); + + it('should return 404 for update non-existent saved query', () => + supertest + .put(`${SAVED_QUERY_BASE_URL}/invalid_id`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send(mockSavedQuery) + .expect(404)); + + it('should return 200 for get saved query', () => + supertest + .post(`${SAVED_QUERY_BASE_URL}/_create`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send(mockSavedQuery) + .expect(200) + .then(({ body }) => + supertest + .get(`${SAVED_QUERY_BASE_URL}/${body.id}`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .expect(200) + .then((res) => { + expect(res.body.id).to.be(body.id); + expect(res.body.attributes.title).to.be(body.attributes.title); + }) + )); + + it('should return 404 for get non-existent saved query', () => + supertest + .get(`${SAVED_QUERY_BASE_URL}/invalid_id`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .expect(404)); + + it('should return 200 for saved query count', () => + supertest + .get(`${SAVED_QUERY_BASE_URL}/_count`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .expect(200)); + + it('should return 200 for find saved queries', () => + supertest + .post(`${SAVED_QUERY_BASE_URL}/_find`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send({}) + .expect(200)); + + it('should return 400 for bad find saved queries request', () => + supertest + .post(`${SAVED_QUERY_BASE_URL}/_find`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send({ foo: 'bar' }) + .expect(400)); + + it('should return 200 for find all saved queries', () => + supertest + .post(`${SAVED_QUERY_BASE_URL}/_all`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .expect(200)); + + it('should return 200 for delete saved query', () => + supertest + .post(`${SAVED_QUERY_BASE_URL}/_create`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .send(mockSavedQuery) + .expect(200) + .then(({ body }) => + supertest + .delete(`${SAVED_QUERY_BASE_URL}/${body.id}`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .expect(200) + )); + + it('should return 404 for get non-existent saved query', () => + supertest + .delete(`${SAVED_QUERY_BASE_URL}/invalid_id`) + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .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..3f2166447f652 100644 --- a/test/examples/search/warnings.ts +++ b/test/examples/search/warnings.ts @@ -26,7 +26,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const esArchiver = getService('esArchiver'); - describe('handling warnings with search source fetch', function () { + // Failing: See https://github.com/elastic/kibana/issues/139879 + describe.skip('handling warnings with search source fetch', function () { const dataViewTitle = 'sample-01,sample-01-rollup'; const fromTime = 'Jun 17, 2022 @ 00:00:00.000'; const toTime = 'Jun 23, 2022 @ 00:00:00.000'; @@ -167,6 +168,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 4145501babb58..8f2a927a4ff24 100644 --- a/test/functional/apps/console/_autocomplete.ts +++ b/test/functional/apps/console/_autocomplete.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import _ from 'lodash'; import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; import { FtrProviderContext } from '../../ftr_provider_context'; @@ -13,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() { @@ -24,6 +25,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Ensure that the text area can be interacted with await PageObjects.console.closeHelpIfExists(); await PageObjects.console.clearTextArea(); + log.debug('setAutocompleteTrace true'); + await PageObjects.console.setAutocompleteTrace(true); + }); + + after(async () => { + log.debug('setAutocompleteTrace false'); + await PageObjects.console.setAutocompleteTrace(false); }); it('should provide basic auto-complete functionality', async () => { @@ -31,10 +39,248 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.console.pressEnter(); await PageObjects.console.enterText(`{\n\t"query": {`); await PageObjects.console.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); await PageObjects.console.promptAutocomplete(); 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(); + }); + + it('should suppress auto-complete on arrow keys', async () => { + await PageObjects.console.enterRequest(); + await PageObjects.console.enterRequest(); + await PageObjects.console.pressEnter(); + const keyPresses = [ + 'pressUp', + 'pressUp', + 'pressDown', + 'pressDown', + 'pressRight', + 'pressRight', + 'pressLeft', + 'pressLeft', + ]; + for (const keyPress of keyPresses) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key', keyPress); + await PageObjects.console[keyPress](); + expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(false); + } + }); + + it('should activate auto-complete for methods case-insensitively', async () => { + const methods = _.sampleSize( + _.compact( + ` + GET GEt GeT Get gET gEt geT get + PUT PUt PuT Put pUT pUt puT put + POST POSt POsT POst PoST PoSt PosT Post pOST pOSt pOsT pOst poST poSt posT post + DELETE DELETe DELEtE DELEte DELeTE DELeTe DELetE DELete DElETE DElETe DElEtE DElEte DEleTE DEleTe DEletE DElete + DeLETE DeLETe DeLEtE DeLEte DeLeTE DeLeTe DeLetE DeLete DelETE DelETe DelEtE DelEte DeleTE DeleTe DeletE Delete + dELETE dELETe dELEtE dELEte dELeTE dELeTe dELetE dELete dElETE dElETe dElEtE dElEte dEleTE dEleTe dEletE dElete + deLETE deLETe deLEtE deLEte deLeTE deLeTe deLetE deLete delETE delETe delEtE delEte deleTE deleTe deletE delete + HEAD HEAd HEaD HEad HeAD HeAd HeaD Head hEAD hEAd hEaD hEad heAD heAd heaD head + `.split(/\s+/m) + ), + 20 // 20 of 112 (approx. one-fifth) should be enough for testing + ); + + for (const method of methods) { + await PageObjects.console.clearTextArea(); + + for (const char of method.slice(0, -1)) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.enterText(char); // e.g. 'P' -> 'Po' -> 'Pos' + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.isAutocompleteVisible() + ); + expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true); + } + + for (const char of [method.at(-1), ' ', '_']) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.enterText(char); // e.g. 'Post ' -> 'Post _' + } + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.isAutocompleteVisible() + ); + expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true); + } + }); + + it('should activate auto-complete for a single character immediately following a slash in URL', async () => { + await PageObjects.console.enterText('GET .kibana'); + + for (const char of ['/', '_']) { + await PageObjects.console.sleepForDebouncePeriod(); + log.debug('Key type "%s"', char); + await PageObjects.console.enterText(char); // e.g. 'GET .kibana/' -> 'GET .kibana/_' + } + + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.isAutocompleteVisible() + ); + expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true); + }); + }); + describe('with a missing comma in query', () => { const LINE_NUMBER = 4; beforeEach(async () => { @@ -48,6 +294,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.console.pressEnter(); await PageObjects.console.pressEnter(); await PageObjects.console.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); await PageObjects.console.promptAutocomplete(); await PageObjects.console.pressEnter(); await retry.try(async () => { @@ -70,6 +317,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should add a comma after the triple quoted strings', async () => { await PageObjects.console.enterText(`{\n\t"query": {\n\t\t"term": """some data"""`); await PageObjects.console.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); await PageObjects.console.promptAutocomplete(); await PageObjects.console.pressEnter(); @@ -111,6 +359,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should insert different templates depending on the value of type', async () => { await PageObjects.console.enterText(`{\n\t"type": "${type}"`); await PageObjects.console.pressEnter(); + await PageObjects.console.sleepForDebouncePeriod(); // Prompt autocomplete for 'settings' await PageObjects.console.promptAutocomplete('s'); diff --git a/test/functional/apps/console/_context_menu.ts b/test/functional/apps/console/_context_menu.ts index 1d7d4a07e3d4d..0d89a762ad910 100644 --- a/test/functional/apps/console/_context_menu.ts +++ b/test/functional/apps/console/_context_menu.ts @@ -16,18 +16,17 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); const toasts = getService('toasts'); - // FLAKY: https://github.com/elastic/kibana/issues/155029 - describe.skip('console context menu', function testContextMenu() { + describe('console context menu', function testContextMenu() { before(async () => { await PageObjects.common.navigateToApp('console'); // Ensure that the text area can be interacted with await PageObjects.console.closeHelpIfExists(); await PageObjects.console.clearTextArea(); + await PageObjects.console.enterRequest(); }); it('should open context menu', async () => { expect(await PageObjects.console.isContextMenuOpen()).to.be(false); - await PageObjects.console.enterRequest(); await PageObjects.console.clickContextMenu(); expect(PageObjects.console.isContextMenuOpen()).to.be.eql(true); }); @@ -80,7 +79,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await browser.switchTab(0); }); - it('should auto indent when auto indent button is clicked', async () => { + it('should toggle auto indent when auto indent button is clicked', async () => { await PageObjects.console.clearTextArea(); await PageObjects.console.enterRequest('GET _search\n{"query": {"match_all": {}}}'); await PageObjects.console.clickContextMenu(); @@ -90,10 +89,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const request = await PageObjects.console.getRequest(); expect(request).to.be.eql('GET _search\n{\n "query": {\n "match_all": {}\n }\n}'); }); - }); - it('should condense when auto indent button is clicked again', async () => { await PageObjects.console.clickContextMenu(); + // Click the auto-indent button again to condense request await PageObjects.console.clickAutoIndentButton(); // Retry until the request is condensed await retry.try(async () => { 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/_esql_view.ts b/test/functional/apps/discover/group2/_esql_view.ts new file mode 100644 index 0000000000000..1f7493b6ff905 --- /dev/null +++ b/test/functional/apps/discover/group2/_esql_view.ts @@ -0,0 +1,134 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const log = getService('log'); + const dataGrid = getService('dataGrid'); + const testSubjects = getService('testSubjects'); + const monacoEditor = getService('monacoEditor'); + const security = getService('security'); + const PageObjects = getPageObjects([ + 'common', + 'discover', + 'header', + 'timePicker', + 'unifiedFieldList', + ]); + + const defaultSettings = { + defaultIndex: 'logstash-*', + 'discover:enableESQL': true, + }; + + 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'); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); + // and load a set of makelogs data + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await kibanaServer.uiSettings.replace(defaultSettings); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + }); + + describe('test', () => { + it('should render esql view correctly', async function () { + await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); + + expect(await testSubjects.exists('showQueryBarMenu')).to.be(true); + expect(await testSubjects.exists('superDatePickerToggleQuickMenuButton')).to.be(true); + expect(await testSubjects.exists('addFilter')).to.be(true); + expect(await testSubjects.exists('dscViewModeDocumentButton')).to.be(true); + expect(await testSubjects.exists('unifiedHistogramChart')).to.be(true); + expect(await testSubjects.exists('unifiedHistogramQueryHits')).to.be(true); + expect(await testSubjects.exists('discoverAlertsButton')).to.be(true); + expect(await testSubjects.exists('shareTopNavButton')).to.be(true); + expect(await testSubjects.exists('docTableExpandToggleColumn')).to.be(true); + expect(await testSubjects.exists('dataGridColumnSortingButton')).to.be(true); + expect(await testSubjects.exists('fieldListFiltersFieldSearch')).to.be(true); + expect(await testSubjects.exists('fieldListFiltersFieldTypeFilterToggle')).to.be(true); + await testSubjects.click('field-@message-showDetails'); + expect(await testSubjects.exists('discoverFieldListPanelEdit-@message')).to.be(true); + + await PageObjects.discover.selectTextBaseLang(); + await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); + + expect(await testSubjects.exists('fieldListFiltersFieldSearch')).to.be(true); + expect(await testSubjects.exists('TextBasedLangEditor')).to.be(true); + expect(await testSubjects.exists('superDatePickerToggleQuickMenuButton')).to.be(true); + + 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 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(false); + expect(await testSubjects.exists('docTableExpandToggleColumn')).to.be(true); + expect(await testSubjects.exists('fieldListFiltersFieldTypeFilterToggle')).to.be(true); + await testSubjects.click('field-@message-showDetails'); + expect(await testSubjects.exists('discoverFieldListPanelEditItem')).to.be(false); + }); + + it('should perform test query correctly', async function () { + 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 XY so it is rendered + expect(await testSubjects.exists('unifiedHistogramChart')).to.be(true); + 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(); + 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, 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' + ); + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.exists('discoverNoResults')).to.be(true); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await PageObjects.header.waitUntilLoadingHasFinished(); + 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(); + 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, 2); + expect(await cell.getVisibleText()).to.be('1'); + }); + }); + }); +} diff --git a/test/functional/apps/discover/group2/_sql_view.ts b/test/functional/apps/discover/group2/_sql_view.ts deleted file mode 100644 index e25d8a1fce36c..0000000000000 --- a/test/functional/apps/discover/group2/_sql_view.ts +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import expect from '@kbn/expect'; - -import { FtrProviderContext } from '../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const kibanaServer = getService('kibanaServer'); - const log = getService('log'); - const dataGrid = getService('dataGrid'); - const testSubjects = getService('testSubjects'); - const monacoEditor = getService('monacoEditor'); - const security = getService('security'); - const PageObjects = getPageObjects([ - 'common', - 'discover', - 'header', - 'timePicker', - 'unifiedFieldList', - ]); - - const defaultSettings = { - defaultIndex: 'logstash-*', - 'discover:enableSql': true, - }; - - // Failing: See https://github.com/elastic/kibana/issues/159194 - describe.skip('discover sql view', async function () { - before(async () => { - await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']); - log.debug('load kibana index with default index pattern'); - await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); - // and load a set of makelogs data - await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); - await kibanaServer.uiSettings.replace(defaultSettings); - await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - }); - - describe('test', () => { - it('should render sql view correctly', async function () { - await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); - - expect(await testSubjects.exists('showQueryBarMenu')).to.be(true); - expect(await testSubjects.exists('superDatePickerToggleQuickMenuButton')).to.be(true); - expect(await testSubjects.exists('addFilter')).to.be(true); - expect(await testSubjects.exists('dscViewModeDocumentButton')).to.be(true); - expect(await testSubjects.exists('unifiedHistogramChart')).to.be(true); - expect(await testSubjects.exists('unifiedHistogramQueryHits')).to.be(true); - expect(await testSubjects.exists('discoverAlertsButton')).to.be(true); - expect(await testSubjects.exists('shareTopNavButton')).to.be(true); - expect(await testSubjects.exists('docTableExpandToggleColumn')).to.be(true); - expect(await testSubjects.exists('dataGridColumnSortingButton')).to.be(true); - expect(await testSubjects.exists('fieldListFiltersFieldSearch')).to.be(true); - expect(await testSubjects.exists('fieldListFiltersFieldTypeFilterToggle')).to.be(true); - await testSubjects.click('field-@message-showDetails'); - expect(await testSubjects.exists('discoverFieldListPanelEdit-@message')).to.be(true); - - await PageObjects.discover.selectTextBaseLang('SQL'); - await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); - - expect(await testSubjects.exists('fieldListFiltersFieldSearch')).to.be(true); - expect(await testSubjects.exists('TextBasedLangEditor')).to.be(true); - expect(await testSubjects.exists('superDatePickerToggleQuickMenuButton')).to.be(true); - - 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 - 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('docTableExpandToggleColumn')).to.be(true); - expect(await testSubjects.exists('fieldListFiltersFieldTypeFilterToggle')).to.be(true); - await testSubjects.click('field-@message-showDetails'); - expect(await testSubjects.exists('discoverFieldListPanelEditItem')).to.be(false); - }); - - 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 monacoEditor.setCodeEditorValue(testQuery); - await testSubjects.click('querySubmitButton'); - await PageObjects.header.waitUntilLoadingHasFinished(); - // here Lens suggests a heatmap 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'); - }); - - 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 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'); - await PageObjects.timePicker.setAbsoluteRange( - 'Sep 19, 2015 @ 06:31:44.000', - 'Sep 19, 2015 @ 06:31:44.000' - ); - await PageObjects.header.waitUntilLoadingHasFinished(); - 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'); - }); - - 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 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'); - }); - }); - }); -} 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.js deleted file mode 100644 index e3ca3f6761113..0000000000000 --- a/test/functional/apps/home/_home.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import expect from '@kbn/expect'; - -export default function ({ getService, getPageObjects }) { - const browser = getService('browser'); - const globalNav = getService('globalNav'); - const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'header', 'home']); - - describe('Kibana takes you home', function describeIndexTests() { - this.tags('includeFirefox'); - - it('clicking on kibana logo should take you to home page', async () => { - await PageObjects.common.navigateToApp('settings'); - await globalNav.clickLogo(); - await PageObjects.header.waitUntilLoadingHasFinished(); - const url = await browser.getCurrentUrl(); - expect(url.includes('/app/home')).to.be(true); - }); - - it('clicking on console on homepage should take you to console app', async () => { - await PageObjects.common.navigateToApp('home'); - await testSubjects.click('homeDevTools'); - const url = await browser.getCurrentUrl(); - expect(url.includes('/app/dev_tools#/console')).to.be(true); - }); - }); -} diff --git a/test/functional/apps/home/_home.ts b/test/functional/apps/home/_home.ts new file mode 100644 index 0000000000000..32248c224ae3f --- /dev/null +++ b/test/functional/apps/home/_home.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const browser = getService('browser'); + const globalNav = getService('globalNav'); + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['common', 'header', 'home']); + + describe('Kibana takes you home', function describeIndexTests() { + this.tags('includeFirefox'); + + it('clicking on kibana logo should take you to home page', async () => { + await PageObjects.common.navigateToApp('settings'); + await globalNav.clickLogo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const url = await browser.getCurrentUrl(); + expect(url.includes('/app/home')).to.be(true); + }); + + it('clicking on console on homepage should take you to console app', async () => { + await PageObjects.common.navigateToApp('home'); + await testSubjects.click('homeDevTools'); + const url = await browser.getCurrentUrl(); + expect(url.includes('/app/dev_tools#/console')).to.be(true); + }); + }); +} 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.js deleted file mode 100644 index 307d848484724..0000000000000 --- a/test/functional/apps/home/index.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 default function ({ getService, loadTestFile }) { - const browser = getService('browser'); - - describe('home app', function () { - before(function () { - return browser.setWindowSize(1200, 800); - }); - - loadTestFile(require.resolve('./_navigation')); - loadTestFile(require.resolve('./_home')); - loadTestFile(require.resolve('./_newsfeed')); - loadTestFile(require.resolve('./_add_data')); - loadTestFile(require.resolve('./_sample_data')); - loadTestFile(require.resolve('./_welcome')); - loadTestFile(require.resolve('./_breadcrumbs')); - }); -} diff --git a/test/functional/apps/home/index.ts b/test/functional/apps/home/index.ts new file mode 100644 index 0000000000000..75629a984df20 --- /dev/null +++ b/test/functional/apps/home/index.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 { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + + describe('home app', function () { + before(function () { + return browser.setWindowSize(1200, 800); + }); + + loadTestFile(require.resolve('./_navigation')); + loadTestFile(require.resolve('./_home')); + loadTestFile(require.resolve('./_newsfeed')); + loadTestFile(require.resolve('./_add_data')); + loadTestFile(require.resolve('./_sample_data')); + loadTestFile(require.resolve('./_welcome')); + loadTestFile(require.resolve('./_breadcrumbs')); + }); +} diff --git a/test/functional/apps/kibana_overview/_analytics.ts b/test/functional/apps/kibana_overview/_analytics.ts index fe43514c7e394..7b9d352e60e31 100644 --- a/test/functional/apps/kibana_overview/_analytics.ts +++ b/test/functional/apps/kibana_overview/_analytics.ts @@ -16,8 +16,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['common', 'header']); - // FLAKY https://github.com/elastic/kibana/issues/135089 - describe.skip('overview page - Analytics apps', function describeIndexTests() { + describe('overview page - Analytics apps', function describeIndexTests() { before(async () => { await esArchiver.load('test/functional/fixtures/es_archiver/logstash_functional'); await kibanaServer.importExport.load( @@ -47,7 +46,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }; for (let i = 0; i < apps.length; i++) { - verifyImageUrl(kbnOverviewAppsCards[i], `kibana_${apps[i]}_light.svg`); + await verifyImageUrl(kbnOverviewAppsCards[i], `kibana_${apps[i]}_light.svg`); } }); 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 60b5b05904ac0..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})`); } @@ -227,6 +239,7 @@ export class CommonPageObject extends FtrService { search = '', disableWelcomePrompt = true, insertTimestamp = true, + retryOnFatalError = true, } = {} ) { let appUrl: string; @@ -273,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}`; @@ -293,6 +306,13 @@ export class CommonPageObject extends FtrService { this.log.debug(msg); throw new Error(msg); } + + if (retryOnFatalError && (await this.isFatalErrorScreen())) { + const msg = `Fatal error screen shown. Let's try refreshing the page once more.`; + this.log.debug(msg); + throw new Error(msg); + } + if (appName === 'discover') { await this.browser.setLocalStorageItem('data.autocompleteFtuePopover', 'true'); } @@ -402,6 +422,10 @@ export class CommonPageObject extends FtrService { return await this.testSubjects.exists('kbnAppWrapper hiddenChrome'); } + async isFatalErrorScreen() { + return await this.testSubjects.exists('fatalErrorScreen'); + } + async waitForTopNavToBeVisible() { await this.retry.try(async () => { const isNavVisible = await this.testSubjects.exists('top-nav'); @@ -493,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 4b5ab3c2c23e1..21a183c832606 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -16,6 +16,7 @@ export class ConsolePageObject extends FtrService { private readonly retry = this.ctx.getService('retry'); private readonly find = this.ctx.getService('find'); private readonly common = this.ctx.getPageObject('common'); + private readonly browser = this.ctx.getService('browser'); public async getVisibleTextFromAceEditor(editor: WebElementWrapper) { const lines = await editor.findAllByClassName('ace_line_group'); @@ -137,19 +138,30 @@ export class ConsolePageObject extends FtrService { // Prompt autocomplete window and provide a initial letter of properties to narrow down the results. E.g. 'b' = 'bool' public async promptAutocomplete(letter = 'b') { const textArea = await this.testSubjects.find('console-textarea'); - await textArea.clickMouseButton(); await textArea.type(letter); await this.retry.waitFor('autocomplete to be visible', () => this.isAutocompleteVisible()); } public async isAutocompleteVisible() { - const element = await this.find.byCssSelector('.ace_autocomplete'); + const element = await this.find.byCssSelector('.ace_autocomplete').catch(() => null); if (!element) return false; const attribute = await element.getAttribute('style'); 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,6 +218,26 @@ export class ConsolePageObject extends FtrService { await textArea.pressKeys(Key.ESCAPE); } + public async pressDown(shift: boolean = false) { + const textArea = await this.testSubjects.find('console-textarea'); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.DOWN] : Key.DOWN); + } + + public async pressLeft(shift: boolean = false) { + const textArea = await this.testSubjects.find('console-textarea'); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.LEFT] : Key.LEFT); + } + + public async pressRight(shift: boolean = false) { + const textArea = await this.testSubjects.find('console-textarea'); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.RIGHT] : Key.RIGHT); + } + + public async pressUp(shift: boolean = false) { + const textArea = await this.testSubjects.find('console-textarea'); + await textArea.pressKeys(shift ? [Key.SHIFT, Key.UP] : Key.UP); + } + public async clearTextArea() { await this.retry.waitForWithTimeout('text area is cleared', 20000, async () => { const textArea = await this.testSubjects.find('console-textarea'); @@ -566,4 +598,16 @@ export class ConsolePageObject extends FtrService { const closeButton = await this.testSubjects.find('consoleHistoryCloseButton'); await closeButton.click(); } + + public async sleepForDebouncePeriod(milliseconds: number = 100) { + // start to sleep after confirming JS engine responds + await this.retry.waitFor('pinging JS engine', () => this.browser.execute('return true;')); + await this.common.sleep(milliseconds); + } + + async setAutocompleteTrace(flag: boolean) { + await this.browser.execute((f: boolean) => { + (window as any).autocomplete_trace = f; + }, flag); + } } 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/management/saved_objects_page.ts b/test/functional/page_objects/management/saved_objects_page.ts index 0ce5396f1472a..b58907d13eabc 100644 --- a/test/functional/page_objects/management/saved_objects_page.ts +++ b/test/functional/page_objects/management/saved_objects_page.ts @@ -190,6 +190,26 @@ export class SavedObjectsPageObject extends FtrService { await option.click(); } + async clickShareToSpaceByTitle(title: string) { + const table = keyBy(await this.getElementsInTable(), 'title'); + // should we check if table size > 0 and log error if not? + if (table[title].menuElement) { + this.log.debug(`we found a context menu element for (${title}) so click it`); + await table[title].menuElement?.click(); + // Wait for context menu to render + const menuPanel = await this.find.byCssSelector('.euiContextMenuPanel'); + await ( + await menuPanel.findByTestSubject('savedObjectsTableAction-share_saved_objects_to_space') + ).click(); + } else { + this.log.debug( + `we didn't find a menu element so should be a "share to space" element for (${title}) to click` + ); + // or the action elements are on the row without the menu + await table[title].copySaveObjectsElement?.click(); + } + } + async clickCopyToSpaceByTitle(title: string) { const table = keyBy(await this.getElementsInTable(), 'title'); // should we check if table size > 0 and log error if not? 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 f19cf47d37bf8..49951b9a3100a 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -23,7 +23,7 @@ declare global { } const EXPOSED_CONFIG_SETTINGS_ERROR = - 'Actual config settings exposed to the browser do not match what is expected; this assertion fails if extra settings are present and/or expected settings are missing'; + 'Actual config settings exposed to the browser do not match list defined in test; this assertion fails if extra settings are present and/or expected settings are missing'; export default function ({ getService }: PluginFunctionalProviderContext) { const appsMenu = getService('appsMenu'); @@ -104,9 +104,11 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'data.search.sessions.management.refreshTimeout (duration)', 'data.search.sessions.maxUpdateRetries (number)', 'data.search.sessions.notTouchedTimeout (duration)', + 'data_views.scriptedFieldsEnabled (any)', // It's a boolean (any because schema.conditional) 'dev_tools.deeplinks.navLinkStatus (string)', 'enterpriseSearch.canDeployEntSearch (boolean)', 'enterpriseSearch.host (string)', + 'enterpriseSearch.ui.enabled (boolean)', 'home.disableWelcomeScreen (boolean)', 'management.deeplinks.navLinkStatus (string)', 'map.emsFileApiUrl (string)', @@ -143,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)', @@ -158,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)', @@ -242,6 +246,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.index_management.enableIndexActions (any)', 'xpack.index_management.enableLegacyTemplates (any)', 'xpack.index_management.dev.enableIndexDetailsPage (boolean)', + 'xpack.index_management.enableIndexStats (any)', 'xpack.infra.sources.default.fields.message (array)', /** * xpack.infra.logs is conditional and will resolve to an object of properties @@ -276,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)', @@ -288,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 @@ -327,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 d13cc53e6f546..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"], @@ -1202,6 +1212,8 @@ "@kbn/security-solution-side-nav/*": ["x-pack/packages/security-solution/side_nav/*"], "@kbn/security-solution-storybook-config": ["x-pack/packages/security-solution/storybook/config"], "@kbn/security-solution-storybook-config/*": ["x-pack/packages/security-solution/storybook/config/*"], + "@kbn/security-solution-upselling": ["x-pack/packages/security-solution/upselling"], + "@kbn/security-solution-upselling/*": ["x-pack/packages/security-solution/upselling/*"], "@kbn/security-test-endpoints-plugin": ["x-pack/test/security_functional/plugins/test_endpoints"], "@kbn/security-test-endpoints-plugin/*": ["x-pack/test/security_functional/plugins/test_endpoints/*"], "@kbn/securitysolution-autocomplete": ["packages/kbn-securitysolution-autocomplete"], @@ -1484,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"], @@ -1641,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/examples/triggers_actions_ui_example/kibana.jsonc b/x-pack/examples/triggers_actions_ui_example/kibana.jsonc index 7b8c1309983a1..9de248572a5bb 100644 --- a/x-pack/examples/triggers_actions_ui_example/kibana.jsonc +++ b/x-pack/examples/triggers_actions_ui_example/kibana.jsonc @@ -13,6 +13,9 @@ "developerExamples", "kibanaReact", "cases" - ] + ], + "optionalPlugins": [ + "spaces" + ], } } diff --git a/x-pack/examples/triggers_actions_ui_example/public/application.tsx b/x-pack/examples/triggers_actions_ui_example/public/application.tsx index c3c2a49ad26da..2da1524f73c37 100644 --- a/x-pack/examples/triggers_actions_ui_example/public/application.tsx +++ b/x-pack/examples/triggers_actions_ui_example/public/application.tsx @@ -25,6 +25,7 @@ import { RulesListNotifyBadgeSandbox } from './components/rules_list_notify_badg import { RuleTagBadgeSandbox } from './components/rule_tag_badge_sandbox'; import { RuleTagFilterSandbox } from './components/rule_tag_filter_sandbox'; import { RuleEventLogListSandbox } from './components/rule_event_log_list_sandbox'; +import { GlobalRuleEventLogListSandbox } from './components/global_rule_event_log_list_sandbox'; import { RuleStatusDropdownSandbox } from './components/rule_status_dropdown_sandbox'; import { RuleStatusFilterSandbox } from './components/rule_status_filter_sandbox'; import { AlertsTableSandbox } from './components/alerts_table_sandbox'; @@ -102,6 +103,14 @@ const TriggersActionsUiExampleApp = ({ )} /> + ( + + + + )} + /> ( diff --git a/x-pack/examples/triggers_actions_ui_example/public/components/global_rule_event_log_list_sandbox.tsx b/x-pack/examples/triggers_actions_ui_example/public/components/global_rule_event_log_list_sandbox.tsx new file mode 100644 index 0000000000000..ec9035536ce99 --- /dev/null +++ b/x-pack/examples/triggers_actions_ui_example/public/components/global_rule_event_log_list_sandbox.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; + +interface SandboxProps { + triggersActionsUi: TriggersAndActionsUIPublicPluginStart; +} + +export const GlobalRuleEventLogListSandbox = ({ triggersActionsUi }: SandboxProps) => { + return ( +
    + {triggersActionsUi.getGlobalRuleEventLogList({ + localStorageKey: 'test-local-storage-key', + filteredRuleTypes: ['apm.error_rate', 'apm.transaction_error_rate'], + })} +
    + ); +}; diff --git a/x-pack/examples/triggers_actions_ui_example/public/components/sidebar.tsx b/x-pack/examples/triggers_actions_ui_example/public/components/sidebar.tsx index 286c61a4607fe..90a44353c646e 100644 --- a/x-pack/examples/triggers_actions_ui_example/public/components/sidebar.tsx +++ b/x-pack/examples/triggers_actions_ui_example/public/components/sidebar.tsx @@ -49,6 +49,11 @@ export const Sidebar = () => { name: 'Run History List', onClick: () => history.push(`/rule_event_log_list`), }, + { + id: 'global_rule_event_log_list', + name: 'Global Run History List', + onClick: () => history.push(`/global_rule_event_log_list`), + }, { id: 'rule_status_dropdown', name: 'Rule Status Dropdown', 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 773b46bdb2ab2..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,9 +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 f2d77c9fb6716..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,21 +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; -}> = ({ title, titleIcon, docLinks, selectedConversation }) => { +}> = ({ isDisabled = false, title, docLinks, selectedConversation }) => { const selectedConnectorId = selectedConversation?.apiConfig?.connectorId; const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = docLinks; @@ -57,7 +56,7 @@ export const AssistantTitle: React.FC<{ const content = useMemo( () => ( - - + + @@ -105,7 +99,6 @@ export const AssistantTitle: React.FC<{ anchorPosition="rightUp" > -

    {i18n.TOOLTIP_TITLE}

    {content}

    @@ -116,9 +109,8 @@ 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 fd8e6d3b2a18f..4ea1ed240870d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx @@ -71,7 +71,6 @@ const AssistantComponent: React.FC = ({ setConversationId, }) => { const { - actionTypeRegistry, assistantTelemetry, augmentMessageCodeBlocks, conversations, @@ -98,11 +97,7 @@ const AssistantComponent: React.FC = ({ const { createConversation } = useConversation(); // Connector details - const { - data: connectors, - isSuccess: areConnectorsFetched, - refetch: refetchConnectors, - } = useLoadConnectors({ http }); + const { data: connectors, isSuccess: areConnectorsFetched } = useLoadConnectors({ http }); const defaultConnectorId = useMemo(() => getDefaultConnector(connectors)?.id, [connectors]); const defaultProvider = useMemo( () => @@ -171,23 +166,14 @@ const AssistantComponent: React.FC = ({ }, [areConnectorsFetched, connectors?.length, currentConversation, setLastConversationId]); const { comments: connectorComments, prompt: connectorPrompt } = useConnectorSetup({ - actionTypeRegistry, - http, - refetchConnectors, + conversation: blockBotConversation, onSetupComplete: () => { bottomRef.current?.scrollIntoView({ behavior: 'auto' }); }, - conversation: blockBotConversation, - isConnectorConfigured: !!connectors?.length, }); - 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); @@ -435,7 +421,6 @@ const AssistantComponent: React.FC = ({ {showTitle && ( = ({ setIsSettingsModalVisible={setIsSettingsModalVisible} setSelectedConversationId={setSelectedConversationId} showAnonymizedValues={showAnonymizedValues} + title={currentTitle} /> )} @@ -475,6 +461,7 @@ const AssistantComponent: React.FC = ({ 0} isSettingsModalVisible={isSettingsModalVisible} setIsSettingsModalVisible={setIsSettingsModalVisible} /> 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 93a52fa81a4a2..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 @@ -11,15 +11,24 @@ import React from 'react'; import { AssistantProvider, useAssistantContext } from '.'; import { httpServiceMock } from '@kbn/core-http-browser-mocks'; import { actionTypeRegistryMock } from '@kbn/triggers-actions-ui-plugin/public/application/action_type_registry.mock'; +import { AssistantAvailability } from '../..'; const actionTypeRegistry = actionTypeRegistryMock.create(); const mockGetInitialConversations = jest.fn(() => ({})); const mockGetComments = jest.fn(() => []); const mockHttp = httpServiceMock.createStartContract({ basePath: '/test' }); +const mockAssistantAvailability: AssistantAvailability = { + hasAssistantPrivilege: false, + hasConnectorsAllPrivilege: true, + hasConnectorsReadPrivilege: true, + isAssistantEnabled: true, +}; const ContextWrapper: React.FC = ({ children }) => ( void; export interface AssistantProviderProps { actionTypeRegistry: ActionTypeRegistryContract; + assistantAvailability: AssistantAvailability; + assistantLangChain: boolean; assistantTelemetry?: AssistantTelemetry; augmentMessageCodeBlocks: (currentConversation: Conversation) => CodeBlockDetails[][]; baseAllow: string[]; @@ -79,10 +81,12 @@ export interface AssistantProviderProps { export interface UseAssistantContext { actionTypeRegistry: ActionTypeRegistryContract; + assistantAvailability: AssistantAvailability; assistantTelemetry?: AssistantTelemetry; augmentMessageCodeBlocks: (currentConversation: Conversation) => CodeBlockDetails[][]; allQuickPrompts: QuickPrompt[]; allSystemPrompts: Prompt[]; + assistantLangChain: boolean; baseAllow: string[]; baseAllowReplacement: string[]; docLinks: Omit; @@ -126,6 +130,8 @@ const AssistantContext = React.createContext(un export const AssistantProvider: React.FC = ({ actionTypeRegistry, + assistantAvailability, + assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, @@ -244,6 +250,8 @@ export const AssistantProvider: React.FC = ({ const value = useMemo( () => ({ actionTypeRegistry, + assistantAvailability, + assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, allQuickPrompts: localStorageQuickPrompts ?? [], @@ -279,6 +287,8 @@ export const AssistantProvider: React.FC = ({ }), [ actionTypeRegistry, + assistantAvailability, + assistantLangChain, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx index 022d131d69fe8..94b78b459c934 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx @@ -62,3 +62,14 @@ export interface AssistantTelemetry { reportAssistantMessageSent: (params: { conversationId: string; role: string }) => void; reportAssistantQuickPrompt: (params: { conversationId: string; promptTitle: string }) => void; } + +export interface AssistantAvailability { + // True when user is Enterprise, or Security Complete PLI for serverless. When false, the Assistant is disabled and unavailable + isAssistantEnabled: boolean; + // When true, the Assistant is hidden and unavailable + hasAssistantPrivilege: boolean; + // When true, user has `All` privilege for `Connectors and Actions` (show/execute/delete/save ui capabilities) + hasConnectorsAllPrivilege: boolean; + // When true, user has `Read` privilege for `Connectors and Actions` (show/execute ui capabilities) + hasConnectorsReadPrivilege: boolean; +} diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_button/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_button/index.tsx index a70ab2a16e5cb..8db849f64fdf6 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_button/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_button/index.tsx @@ -5,32 +5,46 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { EuiCard, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui'; import { GenAiLogo } from '@kbn/stack-connectors-plugin/public/common'; import * as i18n from '../translations'; +import { useAssistantContext } from '../../assistant_context'; export interface ConnectorButtonProps { - setIsConnectorModalVisible: React.Dispatch>; + setIsConnectorModalVisible?: React.Dispatch>; } /** * Simple button component for adding a connector. Note: component is basic and does not handle connector - * add logic. Must pass in `setIsConnectorModalVisible`, see ConnectorSetup component if wanting to manage - * connector add logic. + * add logic. See ConnectorSetup component if wanting to manage connector add logic. */ export const ConnectorButton: React.FC = React.memo( ({ setIsConnectorModalVisible }) => { + const { assistantAvailability } = useAssistantContext(); + + const title = assistantAvailability.hasConnectorsAllPrivilege + ? i18n.ADD_CONNECTOR_TITLE + : i18n.ADD_CONNECTOR_MISSING_PRIVILEGES_TITLE; + const description = assistantAvailability.hasConnectorsAllPrivilege + ? i18n.ADD_CONNECTOR_DESCRIPTION + : i18n.ADD_CONNECTOR_MISSING_PRIVILEGES_DESCRIPTION; + + const onClick = useCallback(() => { + setIsConnectorModalVisible?.(true); + }, [setIsConnectorModalVisible]); + return ( } - title={i18n.ADD_CONNECTOR_TITLE} - description={i18n.ADD_CONNECTOR_DESCRIPTION} - onClick={() => setIsConnectorModalVisible(true)} + title={title} + description={description} + onClick={assistantAvailability.hasConnectorsAllPrivilege ? onClick : undefined} /> diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_missing_callout/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_missing_callout/index.test.tsx new file mode 100644 index 0000000000000..8c2ef67b891a9 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_missing_callout/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { render } from '@testing-library/react'; +import { ConnectorMissingCallout } from '.'; +import { AssistantAvailability } from '../../..'; +import { TestProviders } from '../../mock/test_providers/test_providers'; + +describe('connectorMissingCallout', () => { + describe('when connectors and actions privileges', () => { + describe('are `READ`', () => { + const assistantAvailability: AssistantAvailability = { + hasAssistantPrivilege: true, + hasConnectorsAllPrivilege: false, + hasConnectorsReadPrivilege: true, + isAssistantEnabled: true, + }; + + it('should show connector privileges required button if no connectors exist', async () => { + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('connectorButton')).toBeInTheDocument(); + }); + + it('should NOT show connector privileges required button if at least one connector exists', async () => { + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('connectorButton')).not.toBeInTheDocument(); + }); + }); + + describe('are `NONE`', () => { + const assistantAvailability: AssistantAvailability = { + hasAssistantPrivilege: true, + hasConnectorsAllPrivilege: false, + hasConnectorsReadPrivilege: false, + isAssistantEnabled: true, + }; + + it('should show connector privileges required button', async () => { + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('connectorButton')).toBeInTheDocument(); + }); + }); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_missing_callout/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_missing_callout/index.tsx index 1c56e005892c5..90118b6a5a276 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_missing_callout/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_missing_callout/index.tsx @@ -12,22 +12,24 @@ import { FormattedMessage } from '@kbn/i18n-react'; import * as i18n from '../translations'; import { useAssistantContext } from '../../assistant_context'; import { CONVERSATIONS_TAB } from '../../assistant/settings/assistant_settings'; +import { ConnectorButton } from '../connector_button'; interface Props { + isConnectorConfigured: boolean; isSettingsModalVisible: boolean; setIsSettingsModalVisible: React.Dispatch>; } /** * Error callout to be displayed when there is no connector configured for a conversation. Includes deep-link - * to conversation settings to quickly resolve. + * to conversation settings to quickly resolve. Falls back to connector if privileges aren't met. * * TODO: Add 'quick fix' button to just pick a connector * TODO: Add setting for 'default connector' so we can auto-resolve and not even show this */ export const ConnectorMissingCallout: React.FC = React.memo( - ({ isSettingsModalVisible, setIsSettingsModalVisible }) => { - const { setSelectedSettingsTab } = useAssistantContext(); + ({ isConnectorConfigured, isSettingsModalVisible, setIsSettingsModalVisible }) => { + const { assistantAvailability, setSelectedSettingsTab } = useAssistantContext(); const onConversationSettingsClicked = useCallback(() => { if (!isSettingsModalVisible) { @@ -36,28 +38,40 @@ export const ConnectorMissingCallout: React.FC = React.memo( } }, [isSettingsModalVisible, setIsSettingsModalVisible, setSelectedSettingsTab]); + // Show missing callout if user has all privileges or read privileges and at least 1 connector configured + const showMissingCallout = + assistantAvailability.hasConnectorsAllPrivilege || + (assistantAvailability.hasConnectorsReadPrivilege && isConnectorConfigured); + return ( - -

    - {' '} - - {i18n.MISSING_CONNECTOR_CONVERSATION_SETTINGS_LINK} - - ), - }} - /> -

    -
    + <> + {showMissingCallout ? ( + +

    + {' '} + + {i18n.MISSING_CONNECTOR_CONVERSATION_SETTINGS_LINK} + + ), + }} + /> +

    +
    + ) : ( + + )} + ); } ); 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 f0b47f31e9c27..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,30 +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, @@ -47,6 +41,7 @@ export const ConnectorSelector: React.FC = React.memo( selectedConnectorId, onConnectorSelectionChange, }) => { + const { assistantAvailability } = useAssistantContext(); // Connector Modal State const [isConnectorModalVisible, setIsConnectorModalVisible] = useState(false); const { data: actionTypes } = useLoadActionTypes({ http }); @@ -68,6 +63,7 @@ export const ConnectorSelector: React.FC = React.memo( refetch: refetchConnectors, } = useLoadConnectors({ http }); const isLoading = isLoadingActionTypes || isFetchingActionTypes; + const localIsDisabled = isDisabled || !assistantAvailability.hasConnectorsReadPrivilege; const addNewConnectorOption = useMemo(() => { return { @@ -92,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}

    )}
    @@ -113,6 +110,15 @@ export const ConnectorSelector: React.FC = React.memo( ); }, [connectors]); + // Only include add new connector option if user has privilege + const allConnectorOptions = useMemo( + () => + assistantAvailability.hasConnectorsAllPrivilege + ? [...connectorOptions, addNewConnectorOption] + : [...connectorOptions], + [addNewConnectorOption, assistantAvailability.hasConnectorsAllPrivilege, connectorOptions] + ); + const cleanupAndCloseModal = useCallback(() => { onConnectorModalVisibilityChange?.(false); setIsConnectorModalVisible(false); @@ -126,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] ); @@ -139,23 +143,19 @@ export const ConnectorSelector: React.FC = React.memo( {isConnectorModalVisible && ( { - 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 09b77c642ffcf..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,10 +77,9 @@ export const ConnectorSelectorInline: React.FC = React.memo( onConnectorModalVisibilityChange, selectedConnectorId, selectedConversation, - onConnectorSelectionChange, }) => { const [isOpen, setIsOpen] = useState(false); - const { actionTypeRegistry, http } = useAssistantContext(); + const { actionTypeRegistry, assistantAvailability, http } = useAssistantContext(); const { setApiConfig } = useConversation(); // Connector Modal State const [isConnectorModalVisible, setIsConnectorModalVisible] = useState(false); @@ -111,6 +105,7 @@ export const ConnectorSelectorInline: React.FC = React.memo( const selectedConnectorName = connectors?.find((c) => c.id === selectedConnectorId)?.name ?? i18n.INLINE_CONNECTOR_PLACEHOLDER; + const localIsDisabled = isDisabled || !assistantAvailability.hasConnectorsReadPrivilege; const addNewConnectorOption = useMemo(() => { return { @@ -135,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: ( @@ -148,9 +144,9 @@ export const ConnectorSelectorInline: React.FC = React.memo( dropdownDisplay: ( {connector.name} - {apiProvider && ( + {connectorDetails && ( -

    {apiProvider}

    +

    {connectorDetails}

    )}
    @@ -160,6 +156,15 @@ export const ConnectorSelectorInline: React.FC = React.memo( ); }, [connectors]); + // Only include add new connector option if user has privilege + const allConnectorOptions = useMemo( + () => + assistantAvailability.hasConnectorsAllPrivilege + ? [...connectorOptions, addNewConnectorOption] + : [...connectorOptions], + [addNewConnectorOption, assistantAvailability.hasConnectorsAllPrivilege, connectorOptions] + ); + const cleanupAndCloseModal = useCallback(() => { onConnectorModalVisibilityChange?.(false); setIsConnectorModalVisible(false); @@ -172,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) { @@ -181,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( @@ -236,13 +232,13 @@ export const ConnectorSelectorInline: React.FC = React.memo( @@ -254,7 +250,7 @@ export const ConnectorSelectorInline: React.FC = React.memo( data-test-subj="connectorSelectorPlaceholderButton" iconSide={'right'} iconType="arrowDown" - isDisabled={isDisabled} + isDisabled={localIsDisabled} onClick={onConnectorClick} size="xs" > @@ -266,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 9dac51c5a834c..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 @@ -13,13 +13,8 @@ import styled from 'styled-components'; import { ConnectorAddModal } from '@kbn/triggers-actions-ui-plugin/public/common/constants'; import type { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public'; -import { HttpSetup } from '@kbn/core-http-browser'; -import { ActionType, ActionTypeRegistryContract } 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 { ActionType } from '@kbn/triggers-actions-ui-plugin/public'; +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 +24,9 @@ import { useConversation } from '../../assistant/use_conversation'; import { clearPresentationData, conversationHasNoPresentationData } from './helpers'; 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,26 +36,14 @@ const SkipEuiText = styled(EuiText)` margin-top: 20px; `; -interface Config { - apiProvider: string; -} - export interface ConnectorSetupProps { - isConnectorConfigured: boolean; - actionTypeRegistry: ActionTypeRegistryContract; conversation?: Conversation; - http: HttpSetup; onSetupComplete?: () => void; - refetchConnectors?: () => void; } export const useConnectorSetup = ({ - actionTypeRegistry, conversation = WELCOME_CONVERSATION, - http, - isConnectorConfigured = false, onSetupComplete, - refetchConnectors, }: ConnectorSetupProps): { comments: EuiCommentProps[]; prompt: React.ReactElement; @@ -65,7 +51,13 @@ export const useConnectorSetup = ({ const { appendMessage, setApiConfig, setConversation } = useConversation(); const bottomRef = useRef(null); // Access all conversations so we can add connector to all on initial setup - const { conversations } = useAssistantContext(); + const { actionTypeRegistry, conversations, http } = useAssistantContext(); + const { + data: connectors, + isSuccess: areConnectorsFetched, + refetch: refetchConnectors, + } = useLoadConnectors({ http }); + const isConnectorConfigured = areConnectorsFetched && !!connectors?.length; const [isConnectorModalVisible, setIsConnectorModalVisible] = useState(false); const [showAddConnectorButton, setShowAddConnectorButton] = useState(() => { @@ -188,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 { @@ -231,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 2c8523f2966b9..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', { @@ -73,17 +80,17 @@ export const ADD_CONNECTOR_DESCRIPTION = i18n.translate( } ); -export const CONNECTOR_ADDED_TITLE = i18n.translate( - 'xpack.elasticAssistant.assistant.connectors.addConnectorButton.connectorAddedTitle', +export const ADD_CONNECTOR_MISSING_PRIVILEGES_TITLE = i18n.translate( + 'xpack.elasticAssistant.assistant.connectors.addConnectorButton.missingPrivilegesTitle', { - defaultMessage: 'Generative AI Connector added!', + defaultMessage: 'Generative AI Connector Required', } ); -export const CONNECTOR_ADDED_DESCRIPTION = i18n.translate( - 'xpack.elasticAssistant.assistant.connectors.addConnectorButton.connectorAddedDescription', +export const ADD_CONNECTOR_MISSING_PRIVILEGES_DESCRIPTION = i18n.translate( + 'xpack.elasticAssistant.assistant.connectors.addConnectorButton.missingPrivilegesDescription', { - defaultMessage: 'Ready to continue the conversation...', + defaultMessage: 'Please contact your administrator to enable a Generative AI Connector.', } ); 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 ab625a7b5662a..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 @@ -15,9 +15,10 @@ import { ThemeProvider } from 'styled-components'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { AssistantProvider, AssistantProviderProps } from '../../assistant_context'; -import { Conversation } from '../../assistant_context/types'; +import { AssistantAvailability, Conversation } from '../../assistant_context/types'; interface Props { + assistantAvailability?: AssistantAvailability; children: React.ReactNode; getInitialConversations?: () => Record; providerContext?: Partial; @@ -28,8 +29,16 @@ window.HTMLElement.prototype.scrollIntoView = jest.fn(); const mockGetInitialConversations = () => ({}); +const mockAssistantAvailability: AssistantAvailability = { + hasAssistantPrivilege: false, + hasConnectorsAllPrivilege: true, + hasConnectorsReadPrivilege: true, + isAssistantEnabled: true, +}; + /** A utility for wrapping children in the providers required to run tests */ export const TestProvidersComponent: React.FC = ({ + assistantAvailability = mockAssistantAvailability, children, getInitialConversations = mockGetInitialConversations, providerContext, @@ -56,6 +65,8 @@ export const TestProvidersComponent: React.FC = ({ ; type HistoricalSummaryResponse = t.OutputOf; +/** + * The response type for /internal/observability/slo/_definitions + * + * @private + */ +type FindSloDefinitionsResponse = t.OutputOf; + type GetPreviewDataParams = t.TypeOf; type GetPreviewDataResponse = t.OutputOf; @@ -252,11 +273,12 @@ export { findSLOResponseSchema, getPreviewDataParamsSchema, getPreviewDataResponseSchema, - getSLODiagnosisParamsSchema, getSLOParamsSchema, getSLOResponseSchema, fetchHistoricalSummaryParamsSchema, fetchHistoricalSummaryResponseSchema, + findSloDefinitionsParamsSchema, + findSloDefinitionsResponseSchema, manageSLOParamsSchema, sloResponseSchema, sloWithSummaryResponseSchema, @@ -281,6 +303,7 @@ export type { FetchHistoricalSummaryParams, FetchHistoricalSummaryResponse, HistoricalSummaryResponse, + FindSloDefinitionsResponse, ManageSLOParams, SLOResponse, SLOWithSummaryResponse, diff --git a/x-pack/packages/kbn-slo-schema/src/schema/indicators.ts b/x-pack/packages/kbn-slo-schema/src/schema/indicators.ts index d24d26fbe51dc..07b9c69f4fb97 100644 --- a/x-pack/packages/kbn-slo-schema/src/schema/indicators.ts +++ b/x-pack/packages/kbn-slo-schema/src/schema/indicators.ts @@ -46,13 +46,17 @@ const apmTransactionErrorRateIndicatorSchema = t.type({ const kqlCustomIndicatorTypeSchema = t.literal('sli.kql.custom'); const kqlCustomIndicatorSchema = t.type({ type: kqlCustomIndicatorTypeSchema, - params: t.type({ - index: t.string, - filter: t.string, - good: t.string, - total: t.string, - timestampField: t.string, - }), + params: t.intersection([ + t.type({ + index: t.string, + good: t.string, + total: t.string, + timestampField: t.string, + }), + t.partial({ + filter: t.string, + }), + ]), }); const metricCustomValidAggregations = t.keyof({ @@ -76,13 +80,17 @@ const metricCustomMetricDef = t.type({ const metricCustomIndicatorTypeSchema = t.literal('sli.metric.custom'); const metricCustomIndicatorSchema = t.type({ type: metricCustomIndicatorTypeSchema, - params: t.type({ - index: t.string, - filter: t.string, - good: metricCustomMetricDef, - total: metricCustomMetricDef, - timestampField: t.string, - }), + params: t.intersection([ + t.type({ + index: t.string, + good: metricCustomMetricDef, + total: metricCustomMetricDef, + timestampField: t.string, + }), + t.partial({ + filter: t.string, + }), + ]), }); const rangeHistogramMetricType = t.literal('range'); @@ -117,13 +125,17 @@ const histogramMetricDef = t.union([ const histogramIndicatorTypeSchema = t.literal('sli.histogram.custom'); const histogramIndicatorSchema = t.type({ type: histogramIndicatorTypeSchema, - params: t.type({ - index: t.string, - timestampField: t.string, - filter: t.string, - good: histogramMetricDef, - total: histogramMetricDef, - }), + params: t.intersection([ + t.type({ + index: t.string, + timestampField: t.string, + good: histogramMetricDef, + total: histogramMetricDef, + }), + t.partial({ + filter: t.string, + }), + ]), }); const indicatorDataSchema = t.type({ diff --git a/x-pack/packages/ml/date_picker/src/components/date_picker_wrapper.test.tsx b/x-pack/packages/ml/date_picker/src/components/date_picker_wrapper.test.tsx index 7383cfc78ba7c..f9d189167df9b 100644 --- a/x-pack/packages/ml/date_picker/src/components/date_picker_wrapper.test.tsx +++ b/x-pack/packages/ml/date_picker/src/components/date_picker_wrapper.test.tsx @@ -77,8 +77,7 @@ const mockContextFactory = (addWarning: jest.Mock) => { // eslint-disable-next-line @typescript-eslint/no-var-requires const { of } = require('rxjs'); const mockedUiSettingsKeys = {} as typeof UI_SETTINGS; - const mockedToMountPoint = jest.fn(); - const mockedWrapWithTheme = jest.fn(); + const mockedI18n = jest.fn(); return () => ({ notifications: { @@ -121,8 +120,7 @@ const mockContextFactory = (addWarning: jest.Mock) => { theme$: of(), }, uiSettingsKeys: mockedUiSettingsKeys, - toMountPoint: mockedToMountPoint, - wrapWithTheme: mockedWrapWithTheme, + i18n: mockedI18n, }); }; diff --git a/x-pack/packages/ml/date_picker/src/components/date_picker_wrapper.tsx b/x-pack/packages/ml/date_picker/src/components/date_picker_wrapper.tsx index 562b49f42991e..8d500f7d1a815 100644 --- a/x-pack/packages/ml/date_picker/src/components/date_picker_wrapper.tsx +++ b/x-pack/packages/ml/date_picker/src/components/date_picker_wrapper.tsx @@ -25,6 +25,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { TimeHistoryContract } from '@kbn/data-plugin/public'; import { useUrlState } from '@kbn/ml-url-state'; +import { toMountPoint } from '@kbn/react-kibana-mount'; import { useRefreshIntervalUpdates, useTimeRangeUpdates } from '../hooks/use_timefilter'; import { useDatePickerContext } from '../hooks/use_date_picker_context'; @@ -103,11 +104,10 @@ export const DatePickerWrapper: FC = (props) => { const { data, notifications: { toasts }, - theme: { theme$ }, uiSettings: config, uiSettingsKeys, - wrapWithTheme, - toMountPoint, + theme, + i18n: i18nStart, } = useDatePickerContext(); const isWithinLBreakpoint = useIsWithinMaxBreakpoint('l'); @@ -184,23 +184,21 @@ export const DatePickerWrapper: FC = (props) => { 'The refresh interval in Advanced Settings is shorter than the minimum supported interval.', }), text: toMountPoint( - wrapWithTheme( - - - , - theme$ - ) + + + , + { theme, i18n: i18nStart } ), }, { toastLifeTimeMs: 30000 } diff --git a/x-pack/packages/ml/date_picker/src/hooks/use_date_picker_context.tsx b/x-pack/packages/ml/date_picker/src/hooks/use_date_picker_context.tsx index 19e59b58d392d..28ad6a12de745 100644 --- a/x-pack/packages/ml/date_picker/src/hooks/use_date_picker_context.tsx +++ b/x-pack/packages/ml/date_picker/src/hooks/use_date_picker_context.tsx @@ -9,9 +9,8 @@ import React, { createContext, useContext, type FC } from 'react'; import type { UI_SETTINGS } from '@kbn/data-plugin/common'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import type { CoreSetup, IUiSettingsClient, ThemeServiceStart } from '@kbn/core/public'; +import type { CoreSetup, I18nStart, IUiSettingsClient, ThemeServiceStart } from '@kbn/core/public'; import type { HttpStart } from '@kbn/core/public'; -import type { toMountPoint, wrapWithTheme } from '@kbn/kibana-react-plugin/public'; /** * Date Picker Dependencies to be passed on via `DatePickerContextProvider`. @@ -42,13 +41,9 @@ export interface DatePickerDependencies { */ uiSettingsKeys: typeof UI_SETTINGS; /** - * helper to be used with notifications. + * Internationalisation service */ - wrapWithTheme: typeof wrapWithTheme; - /** - * helper to be used with notifications. - */ - toMountPoint: typeof toMountPoint; + i18n: I18nStart; } /** diff --git a/x-pack/packages/ml/date_picker/tsconfig.json b/x-pack/packages/ml/date_picker/tsconfig.json index ca83d94a598c1..d85c1a4cf4613 100644 --- a/x-pack/packages/ml/date_picker/tsconfig.json +++ b/x-pack/packages/ml/date_picker/tsconfig.json @@ -25,7 +25,7 @@ "@kbn/core", "@kbn/data-views-plugin", "@kbn/ml-is-populated-object", - "@kbn/kibana-react-plugin", "@kbn/ml-query-utils", + "@kbn/react-kibana-mount", ] } diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/index.tsx index 9522f895d90dc..4ce7801dbe8f0 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/body/data_quality_details/index.tsx @@ -22,10 +22,13 @@ import { IlmPhasesEmptyPrompt } from '../../../ilm_phases_empty_prompt'; import { IndicesDetails } from './indices_details'; import { StorageDetails } from './storage_details'; import { PatternRollup, SelectedIndex } from '../../../types'; +import { useDataQualityContext } from '../../data_quality_context'; export 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: ( @@ -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 6926c642b825d..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 @@ -7,7 +7,7 @@ import { actionTypeRegistryMock } from '@kbn/triggers-actions-ui-plugin/public/application/action_type_registry.mock'; import { httpServiceMock } from '@kbn/core-http-browser-mocks'; -import { AssistantProvider } from '@kbn/elastic-assistant'; +import { AssistantAvailability, AssistantProvider } from '@kbn/elastic-assistant'; import { I18nProvider } from '@kbn/i18n-react'; import { euiDarkVars } from '@kbn/ui-theme'; import React from 'react'; @@ -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(() => ({})); @@ -32,11 +33,20 @@ export const TestProvidersComponent: React.FC = ({ children }) => { reportDataQualityIndexChecked: jest.fn(), reportDataQualityCheckAllCompleted: jest.fn(), }; + const mockAssistantAvailability: AssistantAvailability = { + hasAssistantPrivilege: false, + hasConnectorsAllPrivilege: true, + hasConnectorsReadPrivilege: true, + isAssistantEnabled: true, + }; + return ( ({ eui: euiDarkVars, darkMode: true })}> = ({ 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/packages/security-solution/features/src/app_features_keys.ts b/x-pack/packages/security-solution/features/src/app_features_keys.ts new file mode 100644 index 0000000000000..ea3939e2b9f28 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/app_features_keys.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. + */ + +export enum AppFeatureSecurityKey { + /** 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', + + /** + * Enables managing endpoint exceptions on rules and alerts + */ + endpointExceptions = 'endpointExceptions', +} + +export enum AppFeatureCasesKey { + /** + * Enables Cases Connectors + */ + casesConnectors = 'cases_connectors', +} + +export enum AppFeatureAssistantKey { + /** + * Enables Elastic AI Assistant + */ + assistant = 'assistant', +} + +// 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/packages/security-solution/features/src/assistant/kibana_sub_features.ts b/x-pack/packages/security-solution/features/src/assistant/kibana_sub_features.ts new file mode 100644 index 0000000000000..253b98f602c92 --- /dev/null +++ b/x-pack/packages/security-solution/features/src/assistant/kibana_sub_features.ts @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; 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'; + +// This is a sample sub-feature that can be used for future implementations +// @ts-expect-error unused variable +const createConversationSubFeature: SubFeatureConfig = { + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.assistant.createConversationSubFeatureName', + { + defaultMessage: 'Create Conversations', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.assistant.description', + { defaultMessage: 'Create custom conversations.' } + ), + privilegeGroups: [ + { + groupType: 'independent', + privileges: [ + { + api: [], + id: 'create_conversation', + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.assistant.createConversationSubFeatureDetails', + { + defaultMessage: 'Create conversations', + } + ), + includeIn: 'all', + savedObject: { + all: [], + read: [], + }, + ui: ['createConversation'], + }, + ], + }, + ], +}; + +export enum AssistantSubFeatureId { + createConversation = 'createConversationSubFeature', +} + +/** + * 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 + // [AssistantSubFeatureId.createConversation, createConversationSubFeature], + ]) +); 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/packages/security-solution/features/src/security/kibana_sub_features.ts b/x-pack/packages/security-solution/features/src/security/kibana_sub_features.ts new file mode 100644 index 0000000000000..86cbf89f26a6f --- /dev/null +++ b/x-pack/packages/security-solution/features/src/security/kibana_sub_features.ts @@ -0,0 +1,630 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { EXCEPTION_LIST_NAMESPACE_AGNOSTIC } from '@kbn/securitysolution-list-constants'; +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( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointList.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Endpoint List access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointList', + { + defaultMessage: 'Endpoint List', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.endpointList.description', + { + defaultMessage: + 'Displays all hosts running Elastic Defend and their relevant integration details.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [`${APP_ID}-writeEndpointList`, `${APP_ID}-readEndpointList`], + id: 'endpoint_list_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeEndpointList', 'readEndpointList'], + }, + { + api: [`${APP_ID}-readEndpointList`], + id: 'endpoint_list_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readEndpointList'], + }, + ], + }, + ], +}; +const trustedApplicationsSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Trusted Applications access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications', + { + defaultMessage: 'Trusted Applications', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.description', + { + defaultMessage: + 'Helps mitigate conflicts with other software, usually other antivirus or endpoint security applications.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [ + 'lists-all', + 'lists-read', + 'lists-summary', + `${APP_ID}-writeTrustedApplications`, + `${APP_ID}-readTrustedApplications`, + ], + id: 'trusted_applications_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], + read: [], + }, + ui: ['writeTrustedApplications', 'readTrustedApplications'], + }, + { + api: ['lists-read', 'lists-summary', `${APP_ID}-readTrustedApplications`], + id: 'trusted_applications_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readTrustedApplications'], + }, + ], + }, + ], +}; +const hostIsolationExceptionsSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolationExceptions.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Host Isolation Exceptions access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolationExceptions', + { + defaultMessage: 'Host Isolation Exceptions', + } + ), + description: i18n.translate( + '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.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [ + 'lists-all', + 'lists-read', + 'lists-summary', + `${APP_ID}-deleteHostIsolationExceptions`, + `${APP_ID}-readHostIsolationExceptions`, + ], + id: 'host_isolation_exceptions_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], + read: [], + }, + ui: ['readHostIsolationExceptions', 'deleteHostIsolationExceptions'], + }, + { + api: ['lists-read', 'lists-summary', `${APP_ID}-readHostIsolationExceptions`], + id: 'host_isolation_exceptions_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readHostIsolationExceptions'], + }, + ], + }, + ], +}; +const blocklistSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.blockList.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Blocklist access.', + } + ), + name: i18n.translate('securitySolutionPackages.features.featureRegistry.subFeatures.blockList', { + defaultMessage: 'Blocklist', + }), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.blockList.description', + { + defaultMessage: + 'Extend Elastic Defend’s protection against malicious processes and protect against potentially harmful applications.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [ + 'lists-all', + 'lists-read', + 'lists-summary', + `${APP_ID}-writeBlocklist`, + `${APP_ID}-readBlocklist`, + ], + id: 'blocklist_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], + read: [], + }, + ui: ['writeBlocklist', 'readBlocklist'], + }, + { + api: ['lists-read', 'lists-summary', `${APP_ID}-readBlocklist`], + id: 'blocklist_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readBlocklist'], + }, + ], + }, + ], +}; +const eventFiltersSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.eventFilters.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Event Filters access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.eventFilters', + { + defaultMessage: 'Event Filters', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.eventFilters.description', + { + defaultMessage: + 'Filter out endpoint events that you do not need or want stored in Elasticsearch.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [ + 'lists-all', + 'lists-read', + 'lists-summary', + `${APP_ID}-writeEventFilters`, + `${APP_ID}-readEventFilters`, + ], + id: 'event_filters_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], + read: [], + }, + ui: ['writeEventFilters', 'readEventFilters'], + }, + { + api: ['lists-read', 'lists-summary', `${APP_ID}-readEventFilters`], + id: 'event_filters_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readEventFilters'], + }, + ], + }, + ], +}; +const policyManagementSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.policyManagement.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Policy Management access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.policyManagement', + { + defaultMessage: 'Elastic Defend Policy Management', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.policyManagement.description', + { + defaultMessage: + 'Access the Elastic Defend integration policy to configure protections, event collection, and advanced policy features.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [`${APP_ID}-writePolicyManagement`, `${APP_ID}-readPolicyManagement`], + id: 'policy_management_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writePolicyManagement', 'readPolicyManagement'], + }, + { + api: [`${APP_ID}-readPolicyManagement`], + id: 'policy_management_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readPolicyManagement'], + }, + ], + }, + ], +}; + +const responseActionsHistorySubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.responseActionsHistory.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Response Actions History access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.responseActionsHistory', + { + defaultMessage: 'Response Actions History', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.responseActionsHistory.description', + { + defaultMessage: 'Access the history of response actions performed on endpoints.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [`${APP_ID}-writeActionsLogManagement`, `${APP_ID}-readActionsLogManagement`], + id: 'actions_log_management_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeActionsLogManagement', 'readActionsLogManagement'], + }, + { + api: [`${APP_ID}-readActionsLogManagement`], + id: 'actions_log_management_read', + includeIn: 'none', + name: 'Read', + savedObject: { + all: [], + read: [], + }, + ui: ['readActionsLogManagement'], + }, + ], + }, + ], +}; +const hostIsolationSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolation.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Host Isolation access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolation', + { + defaultMessage: 'Host Isolation', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.hostIsolation.description', + { defaultMessage: 'Perform the "isolate" and "release" response actions.' } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [`${APP_ID}-writeHostIsolationRelease`], + id: 'host_isolation_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeHostIsolationRelease'], + }, + ], + }, + ], +}; + +const processOperationsSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.processOperations.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Process Operations access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.processOperations', + { + defaultMessage: 'Process Operations', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.processOperations.description', + { + defaultMessage: 'Perform process-related response actions in the response console.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [`${APP_ID}-writeProcessOperations`], + id: 'process_operations_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeProcessOperations'], + }, + ], + }, + ], +}; +const fileOperationsSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.fileOperations.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for File Operations access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.fileOperations', + { + defaultMessage: 'File Operations', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.fileOperations.description', + { + defaultMessage: 'Perform file-related response actions in the response console.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [`${APP_ID}-writeFileOperations`], + id: 'file_operations_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeFileOperations'], + }, + ], + }, + ], +}; + +// execute operations are not available in 8.7, +// but will be available in 8.8 +const executeActionSubFeature: SubFeatureConfig = { + requireAllSpaces: true, + privilegesTooltip: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.executeOperations.privilegesTooltip', + { + defaultMessage: 'All Spaces is required for Execute Operations access.', + } + ), + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.executeOperations', + { + defaultMessage: 'Execute Operations', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.executeOperations.description', + { + // TODO: Update this description before 8.8 FF + defaultMessage: 'Perform script execution on the endpoint.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [`${APP_ID}-writeExecuteOperations`], + id: 'execute_operations_all', + includeIn: 'none', + name: 'All', + savedObject: { + all: [], + read: [], + }, + ui: ['writeExecuteOperations'], + }, + ], + }, + ], +}; + +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 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], + [SecuritySubFeatureId.eventFilters, eventFiltersSubFeature], + [SecuritySubFeatureId.policyManagement, policyManagementSubFeature], + [SecuritySubFeatureId.responseActionsHistory, responseActionsHistorySubFeature], + [SecuritySubFeatureId.hostIsolation, hostIsolationSubFeature], + [SecuritySubFeatureId.processOperations, processOperationsSubFeature], + [SecuritySubFeatureId.fileOperations, fileOperationsSubFeature], + [SecuritySubFeatureId.executeAction, executeActionSubFeature], + ]) +); 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/packages/security-solution/upselling/README.mdx b/x-pack/packages/security-solution/upselling/README.mdx new file mode 100644 index 0000000000000..62dd77f659062 --- /dev/null +++ b/x-pack/packages/security-solution/upselling/README.mdx @@ -0,0 +1,3 @@ +## Security Solution Upselling + +This package contains the upselling service that registers pages/component/messages and shared upselling components for ESS and Serverless plugins. diff --git a/x-pack/plugins/security_solution_ess/public/common/images/entity_paywall.png b/x-pack/packages/security-solution/upselling/images/entity_paywall.png similarity index 100% rename from x-pack/plugins/security_solution_ess/public/common/images/entity_paywall.png rename to x-pack/packages/security-solution/upselling/images/entity_paywall.png diff --git a/x-pack/packages/security-solution/upselling/jest.config.js b/x-pack/packages/security-solution/upselling/jest.config.js new file mode 100644 index 0000000000000..014db69e5a69d --- /dev/null +++ b/x-pack/packages/security-solution/upselling/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/upselling'], +}; diff --git a/x-pack/packages/security-solution/upselling/kibana.jsonc b/x-pack/packages/security-solution/upselling/kibana.jsonc new file mode 100644 index 0000000000000..0a47f6429d8aa --- /dev/null +++ b/x-pack/packages/security-solution/upselling/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/security-solution-upselling", + "owner": "@elastic/security-threat-hunting-explore" +} \ No newline at end of file diff --git a/x-pack/packages/security-solution/upselling/messages/index.tsx b/x-pack/packages/security-solution/upselling/messages/index.tsx new file mode 100644 index 0000000000000..633f44d21b770 --- /dev/null +++ b/x-pack/packages/security-solution/upselling/messages/index.tsx @@ -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 { i18n } from '@kbn/i18n'; + +export const UPGRADE_INVESTIGATION_GUIDE = (requiredLicense: string) => + i18n.translate('securitySolutionPackages.markdown.insight.upsell', { + defaultMessage: 'Upgrade to {requiredLicense} to make use of insights in investigation guides', + values: { + requiredLicense, + }, + }); diff --git a/x-pack/packages/security-solution/upselling/package.json b/x-pack/packages/security-solution/upselling/package.json new file mode 100644 index 0000000000000..92bd9e35078fa --- /dev/null +++ b/x-pack/packages/security-solution/upselling/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/security-solution-upselling", + "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/upselling/pages/entity_analytics.test.tsx b/x-pack/packages/security-solution/upselling/pages/entity_analytics.test.tsx new file mode 100644 index 0000000000000..244441d69eed8 --- /dev/null +++ b/x-pack/packages/security-solution/upselling/pages/entity_analytics.test.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { render } from '@testing-library/react'; +import EntityAnalyticsUpsellingComponent from './entity_analytics'; + +jest.mock('@kbn/security-solution-navigation', () => { + const original = jest.requireActual('@kbn/security-solution-navigation'); + return { + ...original, + useNavigation: () => ({ + navigateTo: jest.fn(), + }), + }; +}); + +describe('EntityAnalyticsUpselling', () => { + it('should render', () => { + const { getByTestId } = render( + + ); + expect(getByTestId('paywallCardDescription')).toBeInTheDocument(); + }); + + it('should throw exception when requiredLicense and requiredProduct are not provided', () => { + expect(() => render()).toThrow(); + }); + + it('should show product message when requiredProduct is provided', () => { + const { getByTestId } = render( + + ); + + expect(getByTestId('paywallCardDescription')).toHaveTextContent( + 'Entity risk scoring capability is available in our TEST PRODUCT license tier' + ); + }); + + it('should show product badge when requiredProduct is provided', () => { + const { getByText } = render( + + ); + + expect(getByText('TEST PRODUCT')).toBeInTheDocument(); + }); + + it('should show license message when requiredLicense is provided', () => { + const { getByTestId } = render( + + ); + + expect(getByTestId('paywallCardDescription')).toHaveTextContent( + 'This feature is available with TEST LICENSE or higher subscription' + ); + }); + + it('should show license badge when requiredLicense is provided', () => { + const { getByText } = render( + + ); + + expect(getByText('TEST LICENSE')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/packages/security-solution/upselling/pages/entity_analytics.tsx b/x-pack/packages/security-solution/upselling/pages/entity_analytics.tsx new file mode 100644 index 0000000000000..56507dd0f2b46 --- /dev/null +++ b/x-pack/packages/security-solution/upselling/pages/entity_analytics.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 React, { useCallback } from 'react'; +import { + EuiCard, + EuiIcon, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiButton, + EuiTextColor, + EuiImage, + EuiPageHeader, + EuiSpacer, +} from '@elastic/eui'; + +import styled from '@emotion/styled'; +import { useNavigation } from '@kbn/security-solution-navigation'; +import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; +import * as i18n from './translations'; +import paywallPng from '../images/entity_paywall.png'; + +const PaywallDiv = styled.div` + max-width: 75%; + margin: 0 auto; + .euiCard__betaBadgeWrapper { + .euiCard__betaBadge { + width: auto; + } + } + .paywallCardDescription { + padding: 0 15%; + } +`; +const StyledEuiCard = styled(EuiCard)` + span.euiTitle { + max-width: 540px; + display: block; + margin: 0 auto; + } +`; + +const EntityAnalyticsUpsellingComponent = ({ + requiredLicense, + requiredProduct, + subscriptionUrl, +}: { + requiredLicense?: string; + requiredProduct?: string; + subscriptionUrl?: string; +}) => { + const { navigateTo } = useNavigation(); + + const goToSubscription = useCallback(() => { + navigateTo({ url: subscriptionUrl }); + }, [navigateTo, subscriptionUrl]); + + if (!requiredProduct && !requiredLicense) { + throw new Error('requiredProduct or requiredLicense must be defined'); + } + + const upgradeMessage = requiredProduct + ? i18n.UPGRADE_PRODUCT_MESSAGE(requiredProduct) + : i18n.UPGRADE_LICENSE_MESSAGE(requiredLicense ?? ''); + + const requiredProductOrLicense = requiredProduct ?? requiredLicense ?? ''; + + return ( + + + + + + } + display="subdued" + title={ +

    + {i18n.ENTITY_ANALYTICS_LICENSE_DESC} +

    + } + description={false} + paddingSize="xl" + > + + + +

    + {upgradeMessage} +

    +
    + + {subscriptionUrl && ( +
    + + {i18n.UPGRADE_BUTTON(requiredProductOrLicense)} + +
    + )} +
    +
    +
    +
    + + + + + +
    +
    +
    + ); +}; + +EntityAnalyticsUpsellingComponent.displayName = 'EntityAnalyticsUpsellingComponent'; + +// eslint-disable-next-line import/no-default-export +export default React.memo(EntityAnalyticsUpsellingComponent); diff --git a/x-pack/packages/security-solution/upselling/pages/translations.ts b/x-pack/packages/security-solution/upselling/pages/translations.ts new file mode 100644 index 0000000000000..f4dd5b5c081c8 --- /dev/null +++ b/x-pack/packages/security-solution/upselling/pages/translations.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 { i18n } from '@kbn/i18n'; + +export const UPGRADE_LICENSE_MESSAGE = (requiredLicense: string) => + i18n.translate('securitySolutionPackages.entityAnalytics.paywall.upgradeLicenseMessage', { + defaultMessage: 'This feature is available with {requiredLicense} or higher subscription', + values: { + requiredLicense, + }, + }); + +export const UPGRADE_PRODUCT_MESSAGE = (requiredProduct: string) => + i18n.translate('securitySolutionPackages.entityAnalytics.paywall.upgradeProductMessage', { + defaultMessage: + 'Entity risk scoring capability is available in our {requiredProduct} license tier', + values: { + requiredProduct, + }, + }); + +export const UPGRADE_BUTTON = (requiredLicenseOrProduct: string) => + i18n.translate('securitySolutionPackages.entityAnalytics.paywall.upgradeButton', { + defaultMessage: 'Upgrade to {requiredLicenseOrProduct}', + values: { + requiredLicenseOrProduct, + }, + }); + +export const ENTITY_ANALYTICS_LICENSE_DESC = i18n.translate( + 'securitySolutionPackages.entityAnalytics.pageDesc', + { + defaultMessage: 'Detect threats from users and hosts within your network with Entity Analytics', + } +); + +export const ENTITY_ANALYTICS_TITLE = i18n.translate( + 'securitySolutionPackages.entityAnalytics.navigation', + { + defaultMessage: 'Entity Analytics', + } +); diff --git a/x-pack/packages/security-solution/upselling/service/index.ts b/x-pack/packages/security-solution/upselling/service/index.ts new file mode 100644 index 0000000000000..6a71fd9dde2ca --- /dev/null +++ b/x-pack/packages/security-solution/upselling/service/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export { UpsellingService } from './upselling_service'; +export type { + PageUpsellings, + SectionUpsellings, + UpsellingSectionId, + UpsellingMessageId, +} from './types'; diff --git a/x-pack/packages/security-solution/upselling/service/types.ts b/x-pack/packages/security-solution/upselling/service/types.ts new file mode 100644 index 0000000000000..2f5a06c391471 --- /dev/null +++ b/x-pack/packages/security-solution/upselling/service/types.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { SecurityPageName } from '@kbn/security-solution-navigation'; + +export type PageUpsellings = Partial>; +export type MessageUpsellings = Partial>; +export type SectionUpsellings = Partial>; + +export type UpsellingSectionId = + | 'entity_analytics_panel' + | 'endpointPolicyProtections' + | 'osquery_automated_response_actions'; + +export type UpsellingMessageId = 'investigation_guide'; diff --git a/x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.test.tsx b/x-pack/packages/security-solution/upselling/service/upselling_service.test.tsx similarity index 97% rename from x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.test.tsx rename to x-pack/packages/security-solution/upselling/service/upselling_service.test.tsx index 2083e6c21f5c2..a584fcc70f887 100644 --- a/x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.test.tsx +++ b/x-pack/packages/security-solution/upselling/service/upselling_service.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; import { firstValueFrom } from 'rxjs'; -import { SecurityPageName } from '../../../../common'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; import { UpsellingService } from './upselling_service'; const TestComponent = () =>
    {'TEST component'}
    ; diff --git a/x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts b/x-pack/packages/security-solution/upselling/service/upselling_service.ts similarity index 97% rename from x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts rename to x-pack/packages/security-solution/upselling/service/upselling_service.ts index 27d15c1d12768..c362c8be6b9e1 100644 --- a/x-pack/plugins/security_solution/public/common/lib/upsellings/upselling_service.ts +++ b/x-pack/packages/security-solution/upselling/service/upselling_service.ts @@ -7,7 +7,7 @@ import type { Observable } from 'rxjs'; import { BehaviorSubject } from 'rxjs'; -import type { SecurityPageName } from '../../../../common'; +import type { SecurityPageName } from '@kbn/security-solution-navigation'; import type { SectionUpsellings, PageUpsellings, diff --git a/x-pack/packages/security-solution/upselling/tsconfig.json b/x-pack/packages/security-solution/upselling/tsconfig.json new file mode 100644 index 0000000000000..70b145ed91b7d --- /dev/null +++ b/x-pack/packages/security-solution/upselling/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react", + "@emotion/react/types/css-prop", + "@testing-library/jest-dom", + "@testing-library/react", + "@kbn/ambient-ui-types" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx" + ], + "kbn_references": [ + "@kbn/i18n", + "@kbn/security-solution-navigation", + "@kbn/shared-ux-page-kibana-template", + ], + "exclude": [ + "target/**/*" + ] +} 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 new file mode 100644 index 0000000000000..99d08664c96a4 --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/response/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// Latest +export type { ConnectorResponse, ActionTypeConfig } from './types/latest'; +export { connectorResponseSchema } from './schemas/latest'; +export { connectorTypesResponseSchema } from './schemas/latest'; + +// v1 +export type { + ConnectorResponse as ConnectorResponseV1, + 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 new file mode 100644 index 0000000000000..dbb5659baf8c4 --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/response/schemas/latest.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 { 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 new file mode 100644 index 0000000000000..4f8be5b0f344f --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/response/schemas/v1.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 { schema } from '@kbn/config-schema'; + +export const connectorResponseSchema = schema.object({ + id: schema.string(), + name: schema.string(), + config: schema.maybe(schema.recordOf(schema.string(), schema.any())), + connector_type_id: schema.string(), + is_missing_secrets: schema.maybe(schema.boolean()), + is_preconfigured: schema.boolean(), + is_deprecated: schema.boolean(), + 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/latest.ts b/x-pack/plugins/actions/common/routes/connector/response/types/latest.ts new file mode 100644 index 0000000000000..dce95e7328199 --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/response/types/latest.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 './v1'; 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 new file mode 100644 index 0000000000000..5aed107c6f4f6 --- /dev/null +++ b/x-pack/plugins/actions/common/routes/connector/response/types/v1.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TypeOf } from '@kbn/config-schema'; +import { connectorResponseSchemaV1, connectorTypesResponseSchemaV1 } from '..'; + +export type ActionTypeConfig = Record; +type ConnectorResponseSchemaType = TypeOf; + +export interface ConnectorResponse { + id: ConnectorResponseSchemaType['id']; + name: ConnectorResponseSchemaType['name']; + config?: Config; + connector_type_id: ConnectorResponseSchemaType['connector_type_id']; + is_missing_secrets?: ConnectorResponseSchemaType['is_missing_secrets']; + is_preconfigured: ConnectorResponseSchemaType['is_preconfigured']; + is_deprecated: ConnectorResponseSchemaType['is_deprecated']; + is_system_action: ConnectorResponseSchemaType['is_system_action']; + referenced_by_count: ConnectorResponseSchemaType['referenced_by_count']; +} + +type ConnectorTypesResponseSchemaType = TypeOf; +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/docs/openapi/bundled.json b/x-pack/plugins/actions/docs/openapi/bundled.json index 59ca423963caf..67191da3842d6 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.json +++ b/x-pack/plugins/actions/docs/openapi/bundled.json @@ -122,6 +122,9 @@ "examples": { "createIndexConnectorRequest": { "$ref": "#/components/examples/create_index_connector_request" + }, + "createWebhookConnectorRequest": { + "$ref": "#/components/examples/create_webhook_connector_request" } } } @@ -138,6 +141,9 @@ "examples": { "createIndexConnectorResponse": { "$ref": "#/components/examples/create_index_connector_response" + }, + "createWebhookConnectorResponse": { + "$ref": "#/components/examples/create_webhook_connector_response" } } } @@ -2603,13 +2609,88 @@ "title": "Connector request properties for a Webhook connector", "description": "Defines properties for connectors when type is `.webhook`.", "type": "object", - "additionalProperties": true + "properties": { + "authType": { + "type": "string", + "enum": [ + "webhook-authentication-basic", + "webhook-authentication-ssl", + "null" + ], + "description": "The type of authentication to use: basic, SSL, or none.\n" + }, + "ca": { + "type": "string", + "description": "A base64 encoded version of the certificate authority file that the connector can trust to sign and validate certificates. This option is available for all authentication types.\n" + }, + "certType": { + "type": "string", + "description": "If the `authType` is `webhook-authentication-ssl`, specifies whether the certificate authentication data is in a CRT and key file format or a PFX file format.\n", + "enum": [ + "ssl-crt-key", + "ssl-pfx" + ] + }, + "hasAuth": { + "type": "boolean", + "description": "If `true`, a user name and password must be provided for login type authentication.\n" + }, + "headers": { + "type": "object", + "nullable": true, + "description": "A set of key-value pairs sent as headers with the request." + }, + "method": { + "type": "string", + "default": "post", + "enum": [ + "post", + "put" + ], + "description": "The HTTP request method, either `post` or `put`.\n" + }, + "url": { + "type": "string", + "description": "The request URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts.\n" + }, + "verificationMode": { + "type": "string", + "enum": [ + "certificate", + "full", + "none" + ], + "default": "full", + "description": "Controls the verification of certificates. Use `full` to validate that the certificate has an issue date within the `not_before` and `not_after` dates, chains to a trusted certificate authority (CA), and has a hostname or IP address that matches the names within the certificate. Use `certificate` to validate the certificate and verify that it is signed by a trusted authority; this option does not check the certificate hostname. Use `none` to skip certificate validation.\n" + } + } }, "secrets_properties_webhook": { "title": "Connector secrets properties for a Webhook connector", "description": "Defines secrets for connectors when type is `.webhook`.", "type": "object", - "additionalProperties": true + "properties": { + "crt": { + "type": "string", + "description": "If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the CRT or CERT file." + }, + "key": { + "type": "string", + "description": "If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the KEY file." + }, + "pfx": { + "type": "string", + "description": "If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-pfx`, it is a base64 encoded version of the PFX or P12 file." + }, + "password": { + "type": "string", + "description": "The password for HTTP basic authentication or the passphrase for the SSL certificate files. If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required.\n" + }, + "user": { + "type": "string", + "description": "The username for HTTP basic authentication. If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required.\n" + } + } }, "create_connector_request_webhook": { "title": "Create Webhook connector request", @@ -4524,6 +4605,24 @@ } } }, + "create_webhook_connector_request": { + "summary": "Create a webhook connector with SSL authentication.", + "value": { + "name": "my-webhook-connector", + "connector_type_id": ".webhook", + "config": { + "method": "post", + "url": "https://example.com", + "authType": "webhook-authentication-ssl", + "certType": "ssl-crt-key" + }, + "secrets": { + "crt": "QmFnIEF0dH...", + "key": "LS0tLS1CRUdJ...", + "password": "my-passphrase" + } + } + }, "create_index_connector_response": { "summary": "A new index connector.", "value": { @@ -4541,6 +4640,27 @@ "is_system_action": false } }, + "create_webhook_connector_response": { + "summary": "A new webhook connector.", + "value": { + "id": "900eb010-3b9d-11ee-a642-8ffbb94e38bd", + "name": "my-webhook-connector", + "config": { + "method": "post", + "url": "https://example.com", + "authType": "webhook-authentication-ssl", + "certType": "ssl-crt-key", + "verificationMode": "full", + "headers": null, + "hasAuth": true + }, + "connector_type_id": ".webhook", + "is_preconfigured": false, + "is_deprecated": false, + "is_missing_secrets": false, + "is_system_action": false + } + }, "get_connector_response": { "summary": "A list of connector types", "value": { diff --git a/x-pack/plugins/actions/docs/openapi/bundled.yaml b/x-pack/plugins/actions/docs/openapi/bundled.yaml index b090dba90a87a..5da86f4563a6c 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.yaml +++ b/x-pack/plugins/actions/docs/openapi/bundled.yaml @@ -61,6 +61,8 @@ paths: examples: createIndexConnectorRequest: $ref: '#/components/examples/create_index_connector_request' + createWebhookConnectorRequest: + $ref: '#/components/examples/create_webhook_connector_request' responses: '200': description: Indicates a successful call. @@ -71,6 +73,8 @@ paths: examples: createIndexConnectorResponse: $ref: '#/components/examples/create_index_connector_response' + createWebhookConnectorResponse: + $ref: '#/components/examples/create_webhook_connector_response' '401': $ref: '#/components/responses/401' servers: @@ -1753,12 +1757,77 @@ components: title: Connector request properties for a Webhook connector description: Defines properties for connectors when type is `.webhook`. type: object - additionalProperties: true + properties: + authType: + type: string + enum: + - webhook-authentication-basic + - webhook-authentication-ssl + - 'null' + description: | + The type of authentication to use: basic, SSL, or none. + ca: + type: string + description: | + A base64 encoded version of the certificate authority file that the connector can trust to sign and validate certificates. This option is available for all authentication types. + certType: + type: string + description: | + If the `authType` is `webhook-authentication-ssl`, specifies whether the certificate authentication data is in a CRT and key file format or a PFX file format. + enum: + - ssl-crt-key + - ssl-pfx + hasAuth: + type: boolean + description: | + If `true`, a user name and password must be provided for login type authentication. + headers: + type: object + nullable: true + description: A set of key-value pairs sent as headers with the request. + method: + type: string + default: post + enum: + - post + - put + description: | + The HTTP request method, either `post` or `put`. + url: + type: string + description: | + The request URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. + verificationMode: + type: string + enum: + - certificate + - full + - none + default: full + description: | + Controls the verification of certificates. Use `full` to validate that the certificate has an issue date within the `not_before` and `not_after` dates, chains to a trusted certificate authority (CA), and has a hostname or IP address that matches the names within the certificate. Use `certificate` to validate the certificate and verify that it is signed by a trusted authority; this option does not check the certificate hostname. Use `none` to skip certificate validation. secrets_properties_webhook: title: Connector secrets properties for a Webhook connector description: Defines secrets for connectors when type is `.webhook`. type: object - additionalProperties: true + properties: + crt: + type: string + description: If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the CRT or CERT file. + key: + type: string + description: If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the KEY file. + pfx: + type: string + description: If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-pfx`, it is a base64 encoded version of the PFX or P12 file. + password: + type: string + description: | + The password for HTTP basic authentication or the passphrase for the SSL certificate files. If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required. + user: + type: string + description: | + The username for HTTP basic authentication. If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required. create_connector_request_webhook: title: Create Webhook connector request description: | @@ -3130,6 +3199,20 @@ components: connector_type_id: .index config: index: test-index + create_webhook_connector_request: + summary: Create a webhook connector with SSL authentication. + value: + name: my-webhook-connector + connector_type_id: .webhook + config: + method: post + url: https://example.com + authType: webhook-authentication-ssl + certType: ssl-crt-key + secrets: + crt: QmFnIEF0dH... + key: LS0tLS1CRUdJ... + password: my-passphrase create_index_connector_response: summary: A new index connector. value: @@ -3144,6 +3227,24 @@ components: is_deprecated: false is_missing_secrets: false is_system_action: false + create_webhook_connector_response: + summary: A new webhook connector. + value: + id: 900eb010-3b9d-11ee-a642-8ffbb94e38bd + name: my-webhook-connector + config: + method: post + url: https://example.com + authType: webhook-authentication-ssl + certType: ssl-crt-key + verificationMode: full + headers: null + hasAuth: true + connector_type_id: .webhook + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false get_connector_response: summary: A list of connector types value: diff --git a/x-pack/plugins/actions/docs/openapi/components/examples/create_webhook_connector_request.yaml b/x-pack/plugins/actions/docs/openapi/components/examples/create_webhook_connector_request.yaml new file mode 100644 index 0000000000000..e01baea299a80 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/examples/create_webhook_connector_request.yaml @@ -0,0 +1,13 @@ +summary: Create a webhook connector with SSL authentication. +value: + name: my-webhook-connector + connector_type_id: .webhook + config: + method: post + url: https://example.com + authType: webhook-authentication-ssl + certType: ssl-crt-key + secrets: + crt: QmFnIEF0dH... + key: LS0tLS1CRUdJ... + password: my-passphrase \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/examples/create_webhook_connector_response.yaml b/x-pack/plugins/actions/docs/openapi/components/examples/create_webhook_connector_response.yaml new file mode 100644 index 0000000000000..613895b01dac6 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/examples/create_webhook_connector_response.yaml @@ -0,0 +1,17 @@ +summary: A new webhook connector. +value: + id: 900eb010-3b9d-11ee-a642-8ffbb94e38bd + name: my-webhook-connector + config: + method: post + url: https://example.com + authType: webhook-authentication-ssl + certType: ssl-crt-key + verificationMode: full + headers: null + hasAuth: true + connector_type_id: .webhook + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_webhook.yaml index 6fffd356527af..fe45366eca264 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_webhook.yaml @@ -1,5 +1,57 @@ title: Connector request properties for a Webhook connector description: Defines properties for connectors when type is `.webhook`. type: object -additionalProperties: true -# TO-DO: Add the properties for this connector. \ No newline at end of file +properties: + authType: + type: string + enum: + - webhook-authentication-basic + - webhook-authentication-ssl + - "null" + description: > + The type of authentication to use: basic, SSL, or none. + ca: + type: string + description: > + A base64 encoded version of the certificate authority file that the connector can trust to sign and validate certificates. + This option is available for all authentication types. + certType: + type: string + description: > + If the `authType` is `webhook-authentication-ssl`, specifies whether the certificate authentication data is in a CRT and key file format or a PFX file format. + enum: + - ssl-crt-key + - ssl-pfx + hasAuth: + type: boolean + description: > + If `true`, a user name and password must be provided for login type authentication. + headers: + type: object + nullable: true + description: A set of key-value pairs sent as headers with the request. + method: + type: string + default: post + enum: + - post + - put + description: > + The HTTP request method, either `post` or `put`. + url: + type: string + description: > + The request URL. + If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. + verificationMode: + type: string + enum: + - certificate + - full + - none + default: full + description: > + Controls the verification of certificates. + Use `full` to validate that the certificate has an issue date within the `not_before` and `not_after` dates, chains to a trusted certificate authority (CA), and has a hostname or IP address that matches the names within the certificate. + Use `certificate` to validate the certificate and verify that it is signed by a trusted authority; this option does not check the certificate hostname. + Use `none` to skip certificate validation. diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/secrets_properties_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/secrets_properties_webhook.yaml index 5a465932fb898..199e53971f56c 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/secrets_properties_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/secrets_properties_webhook.yaml @@ -1,5 +1,23 @@ title: Connector secrets properties for a Webhook connector description: Defines secrets for connectors when type is `.webhook`. type: object -additionalProperties: true -# TO-DO: Add the properties for this connector. \ No newline at end of file +properties: + crt: + type: string + description: If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the CRT or CERT file. + key: + type: string + description: If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the KEY file. + pfx: + type: string + description: If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-pfx`, it is a base64 encoded version of the PFX or P12 file. + password: + type: string + description: > + The password for HTTP basic authentication or the passphrase for the SSL certificate files. + If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required. + user: + type: string + description: > + The username for HTTP basic authentication. + If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required. \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml index 31336f3487d53..d8d8735db82d8 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml @@ -40,6 +40,8 @@ post: examples: createIndexConnectorRequest: $ref: '../components/examples/create_index_connector_request.yaml' + createWebhookConnectorRequest: + $ref: '../components/examples/create_webhook_connector_request.yaml' responses: '200': description: Indicates a successful call. @@ -50,6 +52,8 @@ post: examples: createIndexConnectorResponse: $ref: '../components/examples/create_index_connector_response.yaml' + createWebhookConnectorResponse: + $ref: '../components/examples/create_webhook_connector_response.yaml' '401': $ref: '../components/responses/401.yaml' servers: diff --git a/x-pack/plugins/actions/server/actions_client.ts b/x-pack/plugins/actions/server/actions_client.ts deleted file mode 100644 index 9b47bd38af3c9..0000000000000 --- a/x-pack/plugins/actions/server/actions_client.ts +++ /dev/null @@ -1,1100 +0,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 { v4 as uuidv4 } from 'uuid'; -import Boom from '@hapi/boom'; -import url from 'url'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; - -import { i18n } from '@kbn/i18n'; -import { omitBy, isUndefined } from 'lodash'; -import { - IScopedClusterClient, - SavedObjectsClientContract, - SavedObjectAttributes, - SavedObject, - KibanaRequest, - SavedObjectsUtils, - Logger, -} from '@kbn/core/server'; -import { AuditLogger } from '@kbn/security-plugin/server'; -import { RunNowResult } from '@kbn/task-manager-plugin/server'; -import { IEventLogClient } from '@kbn/event-log-plugin/server'; -import { KueryNode } from '@kbn/es-query'; -import { - ActionType, - GetGlobalExecutionKPIParams, - GetGlobalExecutionLogParams, - IExecutionLogResult, -} from '../common'; -import { ActionTypeRegistry } from './action_type_registry'; -import { - validateConfig, - validateSecrets, - ActionExecutorContract, - validateConnector, - ActionExecutionSource, - parseDate, -} from './lib'; -import { - ActionResult, - FindActionResult, - RawAction, - InMemoryConnector, - ActionTypeExecutorResult, - ConnectorTokenClientContract, -} from './types'; -import { PreconfiguredActionDisabledModificationError } from './lib/errors/preconfigured_action_disabled_modification'; -import { ExecuteOptions } from './lib/action_executor'; -import { - ExecutionEnqueuer, - ExecuteOptions as EnqueueExecutionOptions, - BulkExecutionEnqueuer, -} from './create_execute_function'; -import { ActionsAuthorization } from './authorization/actions_authorization'; -import { - getAuthorizationModeBySource, - getBulkAuthorizationModeBySource, - AuthorizationMode, -} from './authorization/get_authorization_mode_by_source'; -import { connectorAuditEvent, ConnectorAuditAction } from './lib/audit_events'; -import { trackLegacyRBACExemption } from './lib/track_legacy_rbac_exemption'; -import { isConnectorDeprecated } from './lib/is_connector_deprecated'; -import { ActionsConfigurationUtilities } from './actions_config'; -import { - OAuthClientCredentialsParams, - OAuthJwtParams, - OAuthParams, -} from './routes/get_oauth_access_token'; -import { - getOAuthJwtAccessToken, - GetOAuthJwtConfig, - GetOAuthJwtSecrets, -} from './lib/get_oauth_jwt_access_token'; -import { - getOAuthClientCredentialsAccessToken, - GetOAuthClientCredentialsConfig, - GetOAuthClientCredentialsSecrets, -} from './lib/get_oauth_client_credentials_access_token'; -import { - ACTION_FILTER, - formatExecutionKPIResult, - formatExecutionLogResult, - getExecutionKPIAggregation, - getExecutionLogAggregation, -} from './lib/get_execution_log_aggregation'; - -// We are assuming there won't be many actions. This is why we will load -// all the actions in advance and assume the total count to not go over 10000. -// We'll set this max setting assuming it's never reached. -export const MAX_ACTIONS_RETURNED = 10000; - -interface ActionUpdate { - name: string; - config: SavedObjectAttributes; - secrets: SavedObjectAttributes; -} - -interface Action extends ActionUpdate { - actionTypeId: string; -} - -export interface CreateOptions { - action: Action; - options?: { id?: string }; -} - -interface ConstructorOptions { - logger: Logger; - kibanaIndices: string[]; - scopedClusterClient: IScopedClusterClient; - actionTypeRegistry: ActionTypeRegistry; - unsecuredSavedObjectsClient: SavedObjectsClientContract; - inMemoryConnectors: InMemoryConnector[]; - actionExecutor: ActionExecutorContract; - executionEnqueuer: ExecutionEnqueuer; - ephemeralExecutionEnqueuer: ExecutionEnqueuer; - bulkExecutionEnqueuer: BulkExecutionEnqueuer; - request: KibanaRequest; - authorization: ActionsAuthorization; - auditLogger?: AuditLogger; - usageCounter?: UsageCounter; - connectorTokenClient: ConnectorTokenClientContract; - getEventLogClient: () => Promise; -} - -export interface UpdateOptions { - id: string; - action: ActionUpdate; -} - -interface GetAllOptions { - includeSystemActions?: boolean; -} - -interface ListTypesOptions { - featureId?: string; - includeSystemActionTypes?: boolean; -} - -export class ActionsClient { - private readonly logger: Logger; - private readonly kibanaIndices: string[]; - private readonly scopedClusterClient: IScopedClusterClient; - private readonly unsecuredSavedObjectsClient: SavedObjectsClientContract; - private readonly actionTypeRegistry: ActionTypeRegistry; - private readonly inMemoryConnectors: InMemoryConnector[]; - private readonly actionExecutor: ActionExecutorContract; - private readonly request: KibanaRequest; - private readonly authorization: ActionsAuthorization; - private readonly executionEnqueuer: ExecutionEnqueuer; - private readonly ephemeralExecutionEnqueuer: ExecutionEnqueuer; - private readonly bulkExecutionEnqueuer: BulkExecutionEnqueuer; - private readonly auditLogger?: AuditLogger; - private readonly usageCounter?: UsageCounter; - private readonly connectorTokenClient: ConnectorTokenClientContract; - private readonly getEventLogClient: () => Promise; - - constructor({ - logger, - actionTypeRegistry, - kibanaIndices, - scopedClusterClient, - unsecuredSavedObjectsClient, - inMemoryConnectors, - actionExecutor, - executionEnqueuer, - ephemeralExecutionEnqueuer, - bulkExecutionEnqueuer, - request, - authorization, - auditLogger, - usageCounter, - connectorTokenClient, - getEventLogClient, - }: ConstructorOptions) { - this.logger = logger; - this.actionTypeRegistry = actionTypeRegistry; - this.unsecuredSavedObjectsClient = unsecuredSavedObjectsClient; - this.scopedClusterClient = scopedClusterClient; - this.kibanaIndices = kibanaIndices; - this.inMemoryConnectors = inMemoryConnectors; - this.actionExecutor = actionExecutor; - this.executionEnqueuer = executionEnqueuer; - this.ephemeralExecutionEnqueuer = ephemeralExecutionEnqueuer; - this.bulkExecutionEnqueuer = bulkExecutionEnqueuer; - this.request = request; - this.authorization = authorization; - this.auditLogger = auditLogger; - this.usageCounter = usageCounter; - this.connectorTokenClient = connectorTokenClient; - this.getEventLogClient = getEventLogClient; - } - - /** - * Create an action - */ - public async create({ - action: { actionTypeId, name, config, secrets }, - options, - }: CreateOptions): Promise { - const id = options?.id || SavedObjectsUtils.generateId(); - - try { - await this.authorization.ensureAuthorized({ operation: 'create', actionTypeId }); - } catch (error) { - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.CREATE, - savedObject: { type: 'action', id }, - error, - }) - ); - throw error; - } - - const foundInMemoryConnector = this.inMemoryConnectors.find((connector) => connector.id === id); - - if ( - this.actionTypeRegistry.isSystemActionType(actionTypeId) || - foundInMemoryConnector?.isSystemAction - ) { - throw Boom.badRequest( - i18n.translate('xpack.actions.serverSideErrors.systemActionCreationForbidden', { - defaultMessage: 'System action creation is forbidden. Action type: {actionTypeId}.', - values: { - actionTypeId, - }, - }) - ); - } - - if (foundInMemoryConnector?.isPreconfigured) { - throw Boom.badRequest( - i18n.translate('xpack.actions.serverSideErrors.predefinedIdConnectorAlreadyExists', { - defaultMessage: 'This {id} already exists in a preconfigured action.', - values: { - id, - }, - }) - ); - } - - const actionType = this.actionTypeRegistry.get(actionTypeId); - const configurationUtilities = this.actionTypeRegistry.getUtils(); - - const validatedActionTypeConfig = validateConfig(actionType, config, { - configurationUtilities, - }); - const validatedActionTypeSecrets = validateSecrets(actionType, secrets, { - configurationUtilities, - }); - if (actionType.validate?.connector) { - validateConnector(actionType, { config, secrets }); - } - this.actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); - - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.CREATE, - savedObject: { type: 'action', id }, - outcome: 'unknown', - }) - ); - - const result = await this.unsecuredSavedObjectsClient.create( - 'action', - { - actionTypeId, - name, - isMissingSecrets: false, - config: validatedActionTypeConfig as SavedObjectAttributes, - secrets: validatedActionTypeSecrets as SavedObjectAttributes, - }, - { id } - ); - - return { - id: result.id, - actionTypeId: result.attributes.actionTypeId, - isMissingSecrets: result.attributes.isMissingSecrets, - name: result.attributes.name, - config: result.attributes.config, - isPreconfigured: false, - isSystemAction: false, - isDeprecated: isConnectorDeprecated(result.attributes), - }; - } - - /** - * Update action - */ - public async update({ id, action }: UpdateOptions): Promise { - try { - await this.authorization.ensureAuthorized({ operation: 'update' }); - - const foundInMemoryConnector = this.inMemoryConnectors.find( - (connector) => connector.id === id - ); - - if (foundInMemoryConnector?.isSystemAction) { - throw Boom.badRequest( - i18n.translate('xpack.actions.serverSideErrors.systemActionUpdateForbidden', { - defaultMessage: 'System action {id} can not be updated.', - values: { - id, - }, - }) - ); - } - - if (foundInMemoryConnector?.isPreconfigured) { - throw new PreconfiguredActionDisabledModificationError( - i18n.translate('xpack.actions.serverSideErrors.predefinedActionUpdateDisabled', { - defaultMessage: 'Preconfigured action {id} can not be updated.', - values: { - id, - }, - }), - 'update' - ); - } - } catch (error) { - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.UPDATE, - savedObject: { type: 'action', id }, - error, - }) - ); - throw error; - } - const { attributes, references, version } = - await this.unsecuredSavedObjectsClient.get('action', id); - const { actionTypeId } = attributes; - const { name, config, secrets } = action; - const actionType = this.actionTypeRegistry.get(actionTypeId); - const configurationUtilities = this.actionTypeRegistry.getUtils(); - const validatedActionTypeConfig = validateConfig(actionType, config, { - configurationUtilities, - }); - const validatedActionTypeSecrets = validateSecrets(actionType, secrets, { - configurationUtilities, - }); - if (actionType.validate?.connector) { - validateConnector(actionType, { config, secrets }); - } - - this.actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); - - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.UPDATE, - savedObject: { type: 'action', id }, - outcome: 'unknown', - }) - ); - - const result = await this.unsecuredSavedObjectsClient.create( - 'action', - { - ...attributes, - actionTypeId, - name, - isMissingSecrets: false, - config: validatedActionTypeConfig as SavedObjectAttributes, - secrets: validatedActionTypeSecrets as SavedObjectAttributes, - }, - omitBy( - { - id, - overwrite: true, - references, - version, - }, - isUndefined - ) - ); - - try { - await this.connectorTokenClient.deleteConnectorTokens({ connectorId: id }); - } catch (e) { - this.logger.error( - `Failed to delete auth tokens for connector "${id}" after update: ${e.message}` - ); - } - - return { - id, - actionTypeId: result.attributes.actionTypeId as string, - isMissingSecrets: result.attributes.isMissingSecrets as boolean, - name: result.attributes.name as string, - config: result.attributes.config as Record, - isPreconfigured: false, - isSystemAction: false, - isDeprecated: isConnectorDeprecated(result.attributes), - }; - } - - /** - * Get an action - */ - public async get({ - id, - throwIfSystemAction = true, - }: { - id: string; - throwIfSystemAction?: boolean; - }): Promise { - try { - await this.authorization.ensureAuthorized({ operation: 'get' }); - } catch (error) { - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.GET, - savedObject: { type: 'action', id }, - error, - }) - ); - throw error; - } - - const foundInMemoryConnector = this.inMemoryConnectors.find((connector) => connector.id === id); - - /** - * Getting system connector is not allowed - * if throwIfSystemAction is set to true. - * Default behavior is to throw - */ - if ( - foundInMemoryConnector !== undefined && - foundInMemoryConnector.isSystemAction && - throwIfSystemAction - ) { - throw Boom.notFound(`Connector ${id} not found`); - } - - if (foundInMemoryConnector !== undefined) { - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.GET, - savedObject: { type: 'action', id }, - }) - ); - - return { - id, - actionTypeId: foundInMemoryConnector.actionTypeId, - name: foundInMemoryConnector.name, - isPreconfigured: foundInMemoryConnector.isPreconfigured, - isSystemAction: foundInMemoryConnector.isSystemAction, - isDeprecated: isConnectorDeprecated(foundInMemoryConnector), - }; - } - - const result = await this.unsecuredSavedObjectsClient.get('action', id); - - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.GET, - savedObject: { type: 'action', id }, - }) - ); - - return { - id, - actionTypeId: result.attributes.actionTypeId, - isMissingSecrets: result.attributes.isMissingSecrets, - name: result.attributes.name, - config: result.attributes.config, - isPreconfigured: false, - isSystemAction: false, - isDeprecated: isConnectorDeprecated(result.attributes), - }; - } - - /** - * Get all actions with in-memory connectors - */ - public async getAll({ includeSystemActions = false }: GetAllOptions = {}): Promise< - FindActionResult[] - > { - try { - await this.authorization.ensureAuthorized({ operation: 'get' }); - } catch (error) { - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.FIND, - error, - }) - ); - throw error; - } - - const savedObjectsActions = ( - await this.unsecuredSavedObjectsClient.find({ - perPage: MAX_ACTIONS_RETURNED, - type: 'action', - }) - ).saved_objects.map((rawAction) => - actionFromSavedObject(rawAction, isConnectorDeprecated(rawAction.attributes)) - ); - - savedObjectsActions.forEach(({ id }) => - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.FIND, - savedObject: { type: 'action', id }, - }) - ) - ); - - const inMemoryConnectorsFiltered = includeSystemActions - ? this.inMemoryConnectors - : this.inMemoryConnectors.filter((connector) => !connector.isSystemAction); - - const mergedResult = [ - ...savedObjectsActions, - ...inMemoryConnectorsFiltered.map((inMemoryConnector) => ({ - id: inMemoryConnector.id, - actionTypeId: inMemoryConnector.actionTypeId, - name: inMemoryConnector.name, - isPreconfigured: inMemoryConnector.isPreconfigured, - isDeprecated: isConnectorDeprecated(inMemoryConnector), - isSystemAction: inMemoryConnector.isSystemAction, - })), - ].sort((a, b) => a.name.localeCompare(b.name)); - return await injectExtraFindData(this.kibanaIndices, this.scopedClusterClient, mergedResult); - } - - /** - * Get bulk actions with in-memory list - */ - public async getBulk({ - ids, - throwIfSystemAction = true, - }: { - ids: string[]; - throwIfSystemAction?: boolean; - }): Promise { - try { - await this.authorization.ensureAuthorized({ operation: 'get' }); - } catch (error) { - ids.forEach((id) => - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.GET, - savedObject: { type: 'action', id }, - error, - }) - ) - ); - throw error; - } - - const actionResults = new Array(); - - for (const actionId of ids) { - const action = this.inMemoryConnectors.find( - (inMemoryConnector) => inMemoryConnector.id === actionId - ); - - /** - * Getting system connector is not allowed - * if throwIfSystemAction is set to true. - * Default behavior is to throw - */ - if (action !== undefined && action.isSystemAction && throwIfSystemAction) { - throw Boom.notFound(`Connector ${action.id} not found`); - } - - if (action !== undefined) { - actionResults.push(action); - } - } - - // Fetch action objects in bulk - // Excluding in-memory actions to avoid an not found error, which is already added - const actionSavedObjectsIds = [ - ...new Set( - ids.filter( - (actionId) => !actionResults.find((actionResult) => actionResult.id === actionId) - ) - ), - ]; - - const bulkGetOpts = actionSavedObjectsIds.map((id) => ({ id, type: 'action' })); - const bulkGetResult = await this.unsecuredSavedObjectsClient.bulkGet(bulkGetOpts); - - bulkGetResult.saved_objects.forEach(({ id, error }) => { - if (!error && this.auditLogger) { - this.auditLogger.log( - connectorAuditEvent({ - action: ConnectorAuditAction.GET, - savedObject: { type: 'action', id }, - }) - ); - } - }); - - for (const action of bulkGetResult.saved_objects) { - if (action.error) { - throw Boom.badRequest( - `Failed to load action ${action.id} (${action.error.statusCode}): ${action.error.message}` - ); - } - actionResults.push(actionFromSavedObject(action, isConnectorDeprecated(action.attributes))); - } - - return actionResults; - } - - public async getOAuthAccessToken( - { type, options }: OAuthParams, - configurationUtilities: ActionsConfigurationUtilities - ) { - // Verify that user has edit access - await this.authorization.ensureAuthorized({ operation: 'update' }); - - // Verify that token url is allowed by allowed hosts config - try { - configurationUtilities.ensureUriAllowed(options.tokenUrl); - } catch (err) { - throw Boom.badRequest(err.message); - } - - // Verify that token url contains a hostname and uses https - const parsedUrl = url.parse( - options.tokenUrl, - false /* parseQueryString */, - true /* slashesDenoteHost */ - ); - - if (!parsedUrl.hostname) { - throw Boom.badRequest(`Token URL must contain hostname`); - } - - if (parsedUrl.protocol !== 'https:' && parsedUrl.protocol !== 'http:') { - throw Boom.badRequest(`Token URL must use http or https`); - } - - let accessToken: string | null = null; - if (type === 'jwt') { - const tokenOpts = options as OAuthJwtParams; - - try { - accessToken = await getOAuthJwtAccessToken({ - logger: this.logger, - configurationUtilities, - credentials: { - config: tokenOpts.config as GetOAuthJwtConfig, - secrets: tokenOpts.secrets as GetOAuthJwtSecrets, - }, - tokenUrl: tokenOpts.tokenUrl, - }); - - this.logger.debug( - `Successfully retrieved access token using JWT OAuth with tokenUrl ${ - tokenOpts.tokenUrl - } and config ${JSON.stringify(tokenOpts.config)}` - ); - } catch (err) { - this.logger.debug( - `Failed to retrieve access token using JWT OAuth with tokenUrl ${ - tokenOpts.tokenUrl - } and config ${JSON.stringify(tokenOpts.config)} - ${err.message}` - ); - throw Boom.badRequest(`Failed to retrieve access token`); - } - } else if (type === 'client') { - const tokenOpts = options as OAuthClientCredentialsParams; - try { - accessToken = await getOAuthClientCredentialsAccessToken({ - logger: this.logger, - configurationUtilities, - credentials: { - config: tokenOpts.config as GetOAuthClientCredentialsConfig, - secrets: tokenOpts.secrets as GetOAuthClientCredentialsSecrets, - }, - tokenUrl: tokenOpts.tokenUrl, - oAuthScope: tokenOpts.scope, - }); - - this.logger.debug( - `Successfully retrieved access token using Client Credentials OAuth with tokenUrl ${ - tokenOpts.tokenUrl - }, scope ${tokenOpts.scope} and config ${JSON.stringify(tokenOpts.config)}` - ); - } catch (err) { - this.logger.debug( - `Failed to retrieved access token using Client Credentials OAuth with tokenUrl ${ - tokenOpts.tokenUrl - }, scope ${tokenOpts.scope} and config ${JSON.stringify(tokenOpts.config)} - ${ - err.message - }` - ); - throw Boom.badRequest(`Failed to retrieve access token`); - } - } - - return { accessToken }; - } - - /** - * Delete action - */ - public async delete({ id }: { id: string }) { - try { - await this.authorization.ensureAuthorized({ operation: 'delete' }); - - const foundInMemoryConnector = this.inMemoryConnectors.find( - (connector) => connector.id === id - ); - - if (foundInMemoryConnector?.isSystemAction) { - throw Boom.badRequest( - i18n.translate('xpack.actions.serverSideErrors.systemActionDeletionForbidden', { - defaultMessage: 'System action {id} is not allowed to delete.', - values: { - id, - }, - }) - ); - } - - if (foundInMemoryConnector?.isPreconfigured) { - throw new PreconfiguredActionDisabledModificationError( - i18n.translate('xpack.actions.serverSideErrors.predefinedActionDeleteDisabled', { - defaultMessage: 'Preconfigured action {id} is not allowed to delete.', - values: { - id, - }, - }), - 'delete' - ); - } - } catch (error) { - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.DELETE, - savedObject: { type: 'action', id }, - error, - }) - ); - throw error; - } - - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.DELETE, - outcome: 'unknown', - savedObject: { type: 'action', id }, - }) - ); - - try { - await this.connectorTokenClient.deleteConnectorTokens({ connectorId: id }); - } catch (e) { - this.logger.error( - `Failed to delete auth tokens for connector "${id}" after delete: ${e.message}` - ); - } - - return await this.unsecuredSavedObjectsClient.delete('action', id); - } - - private getSystemActionKibanaPrivileges(connectorId: string, params?: ExecuteOptions['params']) { - const inMemoryConnector = this.inMemoryConnectors.find( - (connector) => connector.id === connectorId - ); - - const additionalPrivileges = inMemoryConnector?.isSystemAction - ? this.actionTypeRegistry.getSystemActionKibanaPrivileges( - inMemoryConnector.actionTypeId, - params - ) - : []; - - return additionalPrivileges; - } - - public async execute({ - actionId, - params, - source, - relatedSavedObjects, - }: Omit): Promise< - ActionTypeExecutorResult - > { - if ( - (await getAuthorizationModeBySource(this.unsecuredSavedObjectsClient, source)) === - AuthorizationMode.RBAC - ) { - const additionalPrivileges = this.getSystemActionKibanaPrivileges(actionId, params); - await this.authorization.ensureAuthorized({ operation: 'execute', additionalPrivileges }); - } else { - trackLegacyRBACExemption('execute', this.usageCounter); - } - - return this.actionExecutor.execute({ - actionId, - params, - source, - request: this.request, - relatedSavedObjects, - actionExecutionId: uuidv4(), - }); - } - - public async enqueueExecution(options: EnqueueExecutionOptions): Promise { - const { source } = options; - if ( - (await getAuthorizationModeBySource(this.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.authorization.ensureAuthorized({ operation: 'execute' }); - } else { - trackLegacyRBACExemption('enqueueExecution', this.usageCounter); - } - return this.executionEnqueuer(this.unsecuredSavedObjectsClient, options); - } - - public async bulkEnqueueExecution(options: EnqueueExecutionOptions[]): Promise { - const sources: Array> = []; - options.forEach((option) => { - if (option.source) { - sources.push(option.source); - } - }); - - const authCounts = await getBulkAuthorizationModeBySource( - this.unsecuredSavedObjectsClient, - sources - ); - if (authCounts[AuthorizationMode.RBAC] > 0) { - /** - * For scheduled executions the additional authorization check - * for system actions (kibana privileges) will be performed - * inside the ActionExecutor at execution time - */ - await this.authorization.ensureAuthorized({ operation: 'execute' }); - } - if (authCounts[AuthorizationMode.Legacy] > 0) { - trackLegacyRBACExemption( - 'bulkEnqueueExecution', - this.usageCounter, - authCounts[AuthorizationMode.Legacy] - ); - } - return this.bulkExecutionEnqueuer(this.unsecuredSavedObjectsClient, options); - } - - public async ephemeralEnqueuedExecution(options: EnqueueExecutionOptions): Promise { - const { source } = options; - if ( - (await getAuthorizationModeBySource(this.unsecuredSavedObjectsClient, source)) === - AuthorizationMode.RBAC - ) { - await this.authorization.ensureAuthorized({ operation: 'execute' }); - } else { - trackLegacyRBACExemption('ephemeralEnqueuedExecution', this.usageCounter); - } - return this.ephemeralExecutionEnqueuer(this.unsecuredSavedObjectsClient, options); - } - - /** - * Return all available action types - * expect system action types - */ - public async listTypes({ - featureId, - includeSystemActionTypes = false, - }: ListTypesOptions = {}): Promise { - const actionTypes = this.actionTypeRegistry.list(featureId); - - const filteredActionTypes = includeSystemActionTypes - ? actionTypes - : actionTypes.filter((actionType) => !Boolean(actionType.isSystemActionType)); - - return filteredActionTypes; - } - - public isActionTypeEnabled( - actionTypeId: string, - options: { notifyUsage: boolean } = { notifyUsage: false } - ) { - return this.actionTypeRegistry.isActionTypeEnabled(actionTypeId, options); - } - - public isPreconfigured(connectorId: string): boolean { - return !!this.inMemoryConnectors.find( - (connector) => connector.isPreconfigured && connector.id === connectorId - ); - } - - public isSystemAction(connectorId: string): boolean { - return !!this.inMemoryConnectors.find( - (connector) => connector.isSystemAction && connector.id === connectorId - ); - } - - public async getGlobalExecutionLogWithAuth({ - dateStart, - dateEnd, - filter, - page, - perPage, - sort, - namespaces, - }: GetGlobalExecutionLogParams): Promise { - this.logger.debug(`getGlobalExecutionLogWithAuth(): getting global execution log`); - - const authorizationTuple = {} as KueryNode; - try { - await this.authorization.ensureAuthorized({ operation: 'get' }); - } catch (error) { - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.GET_GLOBAL_EXECUTION_LOG, - error, - }) - ); - throw error; - } - - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.GET_GLOBAL_EXECUTION_LOG, - }) - ); - - const dateNow = new Date(); - const parsedDateStart = parseDate(dateStart, 'dateStart', dateNow); - const parsedDateEnd = parseDate(dateEnd, 'dateEnd', dateNow); - - const eventLogClient = await this.getEventLogClient(); - - try { - const aggResult = await eventLogClient.aggregateEventsWithAuthFilter( - 'action', - authorizationTuple, - { - start: parsedDateStart.toISOString(), - end: parsedDateEnd.toISOString(), - aggs: getExecutionLogAggregation({ - filter: filter ? `${filter} AND (${ACTION_FILTER})` : ACTION_FILTER, - page, - perPage, - sort, - }), - }, - namespaces, - true - ); - - return formatExecutionLogResult(aggResult); - } catch (err) { - this.logger.debug( - `actionsClient.getGlobalExecutionLogWithAuth(): error searching global event log: ${err.message}` - ); - throw err; - } - } - - public async getGlobalExecutionKpiWithAuth({ - dateStart, - dateEnd, - filter, - namespaces, - }: GetGlobalExecutionKPIParams) { - this.logger.debug(`getGlobalExecutionKpiWithAuth(): getting global execution KPI`); - - const authorizationTuple = {} as KueryNode; - try { - await this.authorization.ensureAuthorized({ operation: 'get' }); - } catch (error) { - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.GET_GLOBAL_EXECUTION_KPI, - error, - }) - ); - throw error; - } - - this.auditLogger?.log( - connectorAuditEvent({ - action: ConnectorAuditAction.GET_GLOBAL_EXECUTION_KPI, - }) - ); - - const dateNow = new Date(); - const parsedDateStart = parseDate(dateStart, 'dateStart', dateNow); - const parsedDateEnd = parseDate(dateEnd, 'dateEnd', dateNow); - - const eventLogClient = await this.getEventLogClient(); - - try { - const aggResult = await eventLogClient.aggregateEventsWithAuthFilter( - 'action', - authorizationTuple, - { - start: parsedDateStart.toISOString(), - end: parsedDateEnd.toISOString(), - aggs: getExecutionKPIAggregation( - filter ? `${filter} AND (${ACTION_FILTER})` : ACTION_FILTER - ), - }, - namespaces, - true - ); - - return formatExecutionKPIResult(aggResult); - } catch (err) { - this.logger.debug( - `actionsClient.getGlobalExecutionKpiWithAuth(): error searching global execution KPI: ${err.message}` - ); - throw err; - } - } -} - -function actionFromSavedObject( - savedObject: SavedObject, - isDeprecated: boolean -): ActionResult { - return { - id: savedObject.id, - ...savedObject.attributes, - isPreconfigured: false, - isDeprecated, - isSystemAction: false, - }; -} - -async function injectExtraFindData( - kibanaIndices: string[], - scopedClusterClient: IScopedClusterClient, - actionResults: ActionResult[] -): Promise { - const aggs: Record = {}; - for (const actionResult of actionResults) { - aggs[actionResult.id] = { - filter: { - bool: { - must: { - nested: { - path: 'references', - query: { - bool: { - filter: { - bool: { - must: [ - { - term: { - 'references.id': actionResult.id, - }, - }, - { - term: { - 'references.type': 'action', - }, - }, - ], - }, - }, - }, - }, - }, - }, - }, - }, - }; - } - const aggregationResult = await scopedClusterClient.asInternalUser.search({ - index: kibanaIndices, - body: { - aggs, - size: 0, - query: { - match_all: {}, - }, - }, - }); - return actionResults.map((actionResult) => ({ - ...actionResult, - // @ts-expect-error aggegation type is not specified - referencedByCount: aggregationResult.aggregations[actionResult.id].doc_count, - })); -} 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.test.ts b/x-pack/plugins/actions/server/actions_client/actions_client.test.ts similarity index 84% rename from x-pack/plugins/actions/server/actions_client.test.ts rename to x-pack/plugins/actions/server/actions_client/actions_client.test.ts index d74a861441c0f..fa7410bb71178 100644 --- a/x-pack/plugins/actions/server/actions_client.test.ts +++ b/x-pack/plugins/actions/server/actions_client/actions_client.test.ts @@ -9,19 +9,19 @@ import { schema } from '@kbn/config-schema'; import moment from 'moment'; import { ByteSizeValue } from '@kbn/config-schema'; -import { ActionTypeRegistry, ActionTypeRegistryOpts } from './action_type_registry'; +import { ActionTypeRegistry, ActionTypeRegistryOpts } from '../action_type_registry'; import { ActionsClient } from './actions_client'; -import { ExecutorType, ActionType } from './types'; +import { ExecutorType, ActionType } from '../types'; import { ActionExecutor, TaskRunnerFactory, ILicenseState, asHttpRequestExecutionSource, -} from './lib'; +} from '../lib'; import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; -import { actionsConfigMock } from './actions_config.mock'; -import { getActionsConfigurationUtilities } from './actions_config'; -import { licenseStateMock } from './lib/license_state.mock'; +import { actionsConfigMock } from '../actions_config.mock'; +import { getActionsConfigurationUtilities } from '../actions_config'; +import { licenseStateMock } from '../lib/license_state.mock'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; import { httpServerMock, @@ -31,26 +31,26 @@ import { } from '@kbn/core/server/mocks'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { actionExecutorMock } from './lib/action_executor.mock'; +import { actionExecutorMock } from '../lib/action_executor.mock'; import { v4 as uuidv4 } from 'uuid'; -import { ActionsAuthorization } from './authorization/actions_authorization'; +import { ActionsAuthorization } from '../authorization/actions_authorization'; import { getAuthorizationModeBySource, AuthorizationMode, getBulkAuthorizationModeBySource, -} from './authorization/get_authorization_mode_by_source'; -import { actionsAuthorizationMock } from './authorization/actions_authorization.mock'; -import { trackLegacyRBACExemption } from './lib/track_legacy_rbac_exemption'; -import { ConnectorTokenClient } from './lib/connector_token_client'; +} from '../authorization/get_authorization_mode_by_source'; +import { actionsAuthorizationMock } from '../authorization/actions_authorization.mock'; +import { trackLegacyRBACExemption } from '../lib/track_legacy_rbac_exemption'; +import { ConnectorTokenClient } from '../lib/connector_token_client'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { Logger } from '@kbn/core/server'; -import { connectorTokenClientMock } from './lib/connector_token_client.mock'; -import { inMemoryMetricsMock } from './monitoring/in_memory_metrics.mock'; -import { getOAuthJwtAccessToken } from './lib/get_oauth_jwt_access_token'; -import { getOAuthClientCredentialsAccessToken } from './lib/get_oauth_client_credentials_access_token'; -import { OAuthParams } from './routes/get_oauth_access_token'; +import { connectorTokenClientMock } from '../lib/connector_token_client.mock'; +import { inMemoryMetricsMock } from '../monitoring/in_memory_metrics.mock'; +import { getOAuthJwtAccessToken } from '../lib/get_oauth_jwt_access_token'; +import { getOAuthClientCredentialsAccessToken } from '../lib/get_oauth_client_credentials_access_token'; +import { OAuthParams } from '../routes/get_oauth_access_token'; import { eventLogClientMock } from '@kbn/event-log-plugin/server/event_log_client.mock'; -import { GetGlobalExecutionKPIParams, GetGlobalExecutionLogParams } from '../common'; +import { GetGlobalExecutionKPIParams, GetGlobalExecutionLogParams } from '../../common'; jest.mock('@kbn/core-saved-objects-utils-server', () => { const actual = jest.requireActual('@kbn/core-saved-objects-utils-server'); @@ -62,11 +62,11 @@ jest.mock('@kbn/core-saved-objects-utils-server', () => { }; }); -jest.mock('./lib/track_legacy_rbac_exemption', () => ({ +jest.mock('../lib/track_legacy_rbac_exemption', () => ({ trackLegacyRBACExemption: jest.fn(), })); -jest.mock('./authorization/get_authorization_mode_by_source', () => { +jest.mock('../authorization/get_authorization_mode_by_source', () => { return { getAuthorizationModeBySource: jest.fn(() => { return 1; @@ -81,10 +81,10 @@ jest.mock('./authorization/get_authorization_mode_by_source', () => { }; }); -jest.mock('./lib/get_oauth_jwt_access_token', () => ({ +jest.mock('../lib/get_oauth_jwt_access_token', () => ({ getOAuthJwtAccessToken: jest.fn(), })); -jest.mock('./lib/get_oauth_client_credentials_access_token', () => ({ +jest.mock('../lib/get_oauth_client_credentials_access_token', () => ({ getOAuthClientCredentialsAccessToken: jest.fn(), })); @@ -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, @@ -1242,364 +1230,6 @@ describe('get()', () => { }); }); -describe('getAll()', () => { - describe('authorization', () => { - function getAllOperation(): ReturnType { - const expectedResult = { - total: 1, - per_page: 10, - page: 1, - saved_objects: [ - { - id: '1', - type: 'type', - attributes: { - name: 'test', - config: { - foo: 'bar', - }, - }, - score: 1, - references: [], - }, - ], - }; - unsecuredSavedObjectsClient.find.mockResolvedValueOnce(expectedResult); - scopedClusterClient.asInternalUser.search.mockResponse( - // @ts-expect-error not full search response - { - aggregations: { - '1': { doc_count: 6 }, - testPreconfigured: { doc_count: 2 }, - }, - } - ); - - actionsClient = new ActionsClient({ - logger, - actionTypeRegistry, - unsecuredSavedObjectsClient, - scopedClusterClient, - kibanaIndices, - actionExecutor, - executionEnqueuer, - ephemeralExecutionEnqueuer, - bulkExecutionEnqueuer, - request, - authorization: authorization as unknown as ActionsAuthorization, - inMemoryConnectors: [ - { - id: 'testPreconfigured', - actionTypeId: '.slack', - secrets: {}, - isPreconfigured: true, - isDeprecated: false, - isSystemAction: false, - name: 'test', - config: { - foo: 'bar', - }, - }, - ], - connectorTokenClient: connectorTokenClientMock.create(), - getEventLogClient, - }); - return actionsClient.getAll(); - } - - test('ensures user is authorised to get the type of action', async () => { - await getAllOperation(); - expect(authorization.ensureAuthorized).toHaveBeenCalledWith({ operation: 'get' }); - }); - - test('throws when user is not authorised to create the type of action', async () => { - authorization.ensureAuthorized.mockRejectedValue( - new Error(`Unauthorized to get all actions`) - ); - - await expect(getAllOperation()).rejects.toMatchInlineSnapshot( - `[Error: Unauthorized to get all actions]` - ); - - expect(authorization.ensureAuthorized).toHaveBeenCalledWith({ operation: 'get' }); - }); - }); - - describe('auditLogger', () => { - test('logs audit event when searching connectors', async () => { - unsecuredSavedObjectsClient.find.mockResolvedValueOnce({ - total: 1, - per_page: 10, - page: 1, - saved_objects: [ - { - id: '1', - type: 'type', - attributes: { - name: 'test', - isMissingSecrets: false, - config: { - foo: 'bar', - }, - }, - score: 1, - references: [], - }, - ], - }); - scopedClusterClient.asInternalUser.search.mockResponse( - // @ts-expect-error not full search response - { - aggregations: { - '1': { doc_count: 6 }, - testPreconfigured: { doc_count: 2 }, - }, - } - ); - - await actionsClient.getAll(); - - expect(auditLogger.log).toHaveBeenCalledWith( - expect.objectContaining({ - event: expect.objectContaining({ - action: 'connector_find', - outcome: 'success', - }), - kibana: { saved_object: { id: '1', type: 'action' } }, - }) - ); - }); - - test('logs audit event when not authorised to search connectors', async () => { - authorization.ensureAuthorized.mockRejectedValue(new Error('Unauthorized')); - - await expect(actionsClient.getAll()).rejects.toThrow(); - - expect(auditLogger.log).toHaveBeenCalledWith( - expect.objectContaining({ - event: expect.objectContaining({ - action: 'connector_find', - outcome: 'failure', - }), - error: { code: 'Error', message: 'Unauthorized' }, - }) - ); - }); - }); - - test('calls unsecuredSavedObjectsClient with parameters and returns inMemoryConnectors correctly', async () => { - const expectedResult = { - total: 1, - per_page: 10, - page: 1, - saved_objects: [ - { - id: '1', - type: 'type', - attributes: { - name: 'test', - isMissingSecrets: false, - config: { - foo: 'bar', - }, - }, - score: 1, - references: [], - }, - ], - }; - unsecuredSavedObjectsClient.find.mockResolvedValueOnce(expectedResult); - scopedClusterClient.asInternalUser.search.mockResponse( - // @ts-expect-error not full search response - { - aggregations: { - '1': { doc_count: 6 }, - testPreconfigured: { doc_count: 2 }, - 'system-connector-.cases': { doc_count: 2 }, - }, - } - ); - - actionsClient = new ActionsClient({ - logger, - actionTypeRegistry, - unsecuredSavedObjectsClient, - scopedClusterClient, - kibanaIndices, - actionExecutor, - executionEnqueuer, - ephemeralExecutionEnqueuer, - bulkExecutionEnqueuer, - request, - authorization: authorization as unknown as ActionsAuthorization, - inMemoryConnectors: [ - { - id: 'testPreconfigured', - actionTypeId: '.slack', - secrets: {}, - isPreconfigured: true, - isDeprecated: false, - isSystemAction: false, - name: 'test', - config: { - foo: 'bar', - }, - }, - /** - * System actions will not - * be returned from getAll - * if no options are provided - */ - { - id: 'system-connector-.cases', - actionTypeId: '.cases', - name: 'System action: .cases', - config: {}, - secrets: {}, - isDeprecated: false, - isMissingSecrets: false, - isPreconfigured: false, - isSystemAction: true, - }, - ], - connectorTokenClient: connectorTokenClientMock.create(), - getEventLogClient, - }); - - const result = await actionsClient.getAll(); - - expect(result).toEqual([ - { - id: '1', - name: 'test', - isMissingSecrets: false, - config: { foo: 'bar' }, - isPreconfigured: false, - isDeprecated: false, - isSystemAction: false, - referencedByCount: 6, - }, - { - id: 'testPreconfigured', - actionTypeId: '.slack', - name: 'test', - isPreconfigured: true, - isSystemAction: false, - isDeprecated: false, - referencedByCount: 2, - }, - ]); - }); - - test('get system actions correctly', async () => { - const expectedResult = { - total: 1, - per_page: 10, - page: 1, - saved_objects: [ - { - id: '1', - type: 'type', - attributes: { - name: 'test', - isMissingSecrets: false, - config: { - foo: 'bar', - }, - }, - score: 1, - references: [], - }, - ], - }; - unsecuredSavedObjectsClient.find.mockResolvedValueOnce(expectedResult); - scopedClusterClient.asInternalUser.search.mockResponse( - // @ts-expect-error not full search response - { - aggregations: { - '1': { doc_count: 6 }, - testPreconfigured: { doc_count: 2 }, - 'system-connector-.cases': { doc_count: 2 }, - }, - } - ); - - actionsClient = new ActionsClient({ - logger, - actionTypeRegistry, - unsecuredSavedObjectsClient, - scopedClusterClient, - kibanaIndices, - actionExecutor, - executionEnqueuer, - ephemeralExecutionEnqueuer, - bulkExecutionEnqueuer, - request, - authorization: authorization as unknown as ActionsAuthorization, - inMemoryConnectors: [ - { - id: 'testPreconfigured', - actionTypeId: '.slack', - secrets: {}, - isPreconfigured: true, - isDeprecated: false, - isSystemAction: false, - name: 'test', - config: { - foo: 'bar', - }, - }, - { - id: 'system-connector-.cases', - actionTypeId: '.cases', - name: 'System action: .cases', - config: {}, - secrets: {}, - isDeprecated: false, - isMissingSecrets: false, - isPreconfigured: false, - isSystemAction: true, - }, - ], - connectorTokenClient: connectorTokenClientMock.create(), - getEventLogClient, - }); - - const result = await actionsClient.getAll({ includeSystemActions: true }); - - expect(result).toEqual([ - { - actionTypeId: '.cases', - id: 'system-connector-.cases', - isDeprecated: false, - isPreconfigured: false, - isSystemAction: true, - name: 'System action: .cases', - referencedByCount: 2, - }, - { - id: '1', - name: 'test', - isMissingSecrets: false, - config: { foo: 'bar' }, - isPreconfigured: false, - isDeprecated: false, - isSystemAction: false, - referencedByCount: 6, - }, - { - id: 'testPreconfigured', - actionTypeId: '.slack', - name: 'test', - isPreconfigured: true, - isSystemAction: false, - isDeprecated: false, - referencedByCount: 2, - }, - ]); - }); -}); - describe('getBulk()', () => { describe('authorization', () => { function getBulkOperation(): ReturnType { @@ -1637,7 +1267,6 @@ describe('getBulk()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1776,7 +1405,6 @@ describe('getBulk()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1872,7 +1500,6 @@ describe('getBulk()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -1947,7 +1574,6 @@ describe('getBulk()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2033,7 +1659,6 @@ describe('getOAuthAccessToken()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2416,7 +2041,6 @@ describe('delete()', () => { }, ], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2453,7 +2077,6 @@ describe('delete()', () => { }, ], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -2969,7 +2592,6 @@ describe('update()', () => { }, ], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3013,7 +2635,6 @@ describe('update()', () => { }, ], actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3122,7 +2743,6 @@ describe('execute()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3187,7 +2807,6 @@ describe('execute()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3251,7 +2870,6 @@ describe('execute()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3387,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 () => { @@ -3591,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', @@ -3800,7 +3173,6 @@ describe('isPreconfigured()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3851,7 +3223,6 @@ describe('isPreconfigured()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3904,7 +3275,6 @@ describe('isSystemAction()', () => { scopedClusterClient, kibanaIndices, actionExecutor, - executionEnqueuer, ephemeralExecutionEnqueuer, bulkExecutionEnqueuer, request, @@ -3955,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 new file mode 100644 index 0000000000000..392b5ec7354b6 --- /dev/null +++ b/x-pack/plugins/actions/server/actions_client/actions_client.ts @@ -0,0 +1,960 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { v4 as uuidv4 } from 'uuid'; +import Boom from '@hapi/boom'; +import url from 'url'; +import { UsageCounter } from '@kbn/usage-collection-plugin/server'; + +import { i18n } from '@kbn/i18n'; +import { omitBy, isUndefined } from 'lodash'; +import { + IScopedClusterClient, + SavedObjectsClientContract, + SavedObjectAttributes, + KibanaRequest, + SavedObjectsUtils, + Logger, +} from '@kbn/core/server'; +import { AuditLogger } from '@kbn/security-plugin/server'; +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 { + GetGlobalExecutionKPIParams, + GetGlobalExecutionLogParams, + IExecutionLogResult, +} from '../../common'; +import { ActionTypeRegistry } from '../action_type_registry'; +import { + validateConfig, + validateSecrets, + ActionExecutorContract, + validateConnector, + ActionExecutionSource, + parseDate, +} from '../lib'; +import { + ActionResult, + RawAction, + InMemoryConnector, + ActionTypeExecutorResult, + ConnectorTokenClientContract, +} from '../types'; +import { PreconfiguredActionDisabledModificationError } from '../lib/errors/preconfigured_action_disabled_modification'; +import { ExecuteOptions } from '../lib/action_executor'; +import { + ExecutionEnqueuer, + ExecuteOptions as EnqueueExecutionOptions, + BulkExecutionEnqueuer, +} from '../create_execute_function'; +import { ActionsAuthorization } from '../authorization/actions_authorization'; +import { + getAuthorizationModeBySource, + getBulkAuthorizationModeBySource, + AuthorizationMode, +} from '../authorization/get_authorization_mode_by_source'; +import { connectorAuditEvent, ConnectorAuditAction } from '../lib/audit_events'; +import { trackLegacyRBACExemption } from '../lib/track_legacy_rbac_exemption'; +import { ActionsConfigurationUtilities } from '../actions_config'; +import { + OAuthClientCredentialsParams, + OAuthJwtParams, + OAuthParams, +} from '../routes/get_oauth_access_token'; +import { + getOAuthJwtAccessToken, + GetOAuthJwtConfig, + GetOAuthJwtSecrets, +} from '../lib/get_oauth_jwt_access_token'; +import { + getOAuthClientCredentialsAccessToken, + GetOAuthClientCredentialsConfig, + GetOAuthClientCredentialsSecrets, +} from '../lib/get_oauth_client_credentials_access_token'; +import { + ACTION_FILTER, + formatExecutionKPIResult, + formatExecutionLogResult, + getExecutionKPIAggregation, + 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; + config: SavedObjectAttributes; + secrets: SavedObjectAttributes; +} + +interface Action extends ActionUpdate { + actionTypeId: string; +} + +export interface CreateOptions { + action: Action; + options?: { id?: string }; +} + +export interface ConstructorOptions { + logger: Logger; + kibanaIndices: string[]; + scopedClusterClient: IScopedClusterClient; + actionTypeRegistry: ActionTypeRegistry; + unsecuredSavedObjectsClient: SavedObjectsClientContract; + inMemoryConnectors: InMemoryConnector[]; + actionExecutor: ActionExecutorContract; + ephemeralExecutionEnqueuer: ExecutionEnqueuer; + bulkExecutionEnqueuer: BulkExecutionEnqueuer; + request: KibanaRequest; + authorization: ActionsAuthorization; + auditLogger?: AuditLogger; + usageCounter?: UsageCounter; + connectorTokenClient: ConnectorTokenClientContract; + getEventLogClient: () => Promise; +} + +export interface UpdateOptions { + id: string; + action: ActionUpdate; +} + +export interface ActionsClientContext { + logger: Logger; + kibanaIndices: string[]; + scopedClusterClient: IScopedClusterClient; + unsecuredSavedObjectsClient: SavedObjectsClientContract; + actionTypeRegistry: ActionTypeRegistry; + inMemoryConnectors: InMemoryConnector[]; + actionExecutor: ActionExecutorContract; + request: KibanaRequest; + authorization: ActionsAuthorization; + ephemeralExecutionEnqueuer: ExecutionEnqueuer; + bulkExecutionEnqueuer: BulkExecutionEnqueuer; + auditLogger?: AuditLogger; + usageCounter?: UsageCounter; + connectorTokenClient: ConnectorTokenClientContract; + getEventLogClient: () => Promise; +} + +export class ActionsClient { + private readonly context: ActionsClientContext; + + constructor({ + logger, + actionTypeRegistry, + kibanaIndices, + scopedClusterClient, + unsecuredSavedObjectsClient, + inMemoryConnectors, + actionExecutor, + ephemeralExecutionEnqueuer, + bulkExecutionEnqueuer, + request, + authorization, + auditLogger, + usageCounter, + connectorTokenClient, + getEventLogClient, + }: ConstructorOptions) { + this.context = { + logger, + actionTypeRegistry, + unsecuredSavedObjectsClient, + scopedClusterClient, + kibanaIndices, + inMemoryConnectors, + actionExecutor, + ephemeralExecutionEnqueuer, + bulkExecutionEnqueuer, + request, + authorization, + auditLogger, + usageCounter, + connectorTokenClient, + getEventLogClient, + }; + } + + /** + * Create an action + */ + public async create({ + action: { actionTypeId, name, config, secrets }, + options, + }: CreateOptions): Promise { + const id = options?.id || SavedObjectsUtils.generateId(); + + try { + await this.context.authorization.ensureAuthorized({ + operation: 'create', + actionTypeId, + }); + } catch (error) { + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.CREATE, + savedObject: { type: 'action', id }, + error, + }) + ); + throw error; + } + + const foundInMemoryConnector = this.context.inMemoryConnectors.find( + (connector) => connector.id === id + ); + + if ( + this.context.actionTypeRegistry.isSystemActionType(actionTypeId) || + foundInMemoryConnector?.isSystemAction + ) { + throw Boom.badRequest( + i18n.translate('xpack.actions.serverSideErrors.systemActionCreationForbidden', { + defaultMessage: 'System action creation is forbidden. Action type: {actionTypeId}.', + values: { + actionTypeId, + }, + }) + ); + } + + if (foundInMemoryConnector?.isPreconfigured) { + throw Boom.badRequest( + i18n.translate('xpack.actions.serverSideErrors.predefinedIdConnectorAlreadyExists', { + defaultMessage: 'This {id} already exists in a preconfigured action.', + values: { + id, + }, + }) + ); + } + + const actionType = this.context.actionTypeRegistry.get(actionTypeId); + const configurationUtilities = this.context.actionTypeRegistry.getUtils(); + const validatedActionTypeConfig = validateConfig(actionType, config, { + configurationUtilities, + }); + const validatedActionTypeSecrets = validateSecrets(actionType, secrets, { + configurationUtilities, + }); + if (actionType.validate?.connector) { + validateConnector(actionType, { config, secrets }); + } + this.context.actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); + + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.CREATE, + savedObject: { type: 'action', id }, + outcome: 'unknown', + }) + ); + + const result = await this.context.unsecuredSavedObjectsClient.create( + 'action', + { + actionTypeId, + name, + isMissingSecrets: false, + config: validatedActionTypeConfig as SavedObjectAttributes, + secrets: validatedActionTypeSecrets as SavedObjectAttributes, + }, + { id } + ); + + return { + id: result.id, + actionTypeId: result.attributes.actionTypeId, + isMissingSecrets: result.attributes.isMissingSecrets, + name: result.attributes.name, + config: result.attributes.config, + isPreconfigured: false, + isSystemAction: false, + isDeprecated: isConnectorDeprecated(result.attributes), + }; + } + + /** + * Update action + */ + public async update({ id, action }: UpdateOptions): Promise { + try { + await this.context.authorization.ensureAuthorized({ operation: 'update' }); + + const foundInMemoryConnector = this.context.inMemoryConnectors.find( + (connector) => connector.id === id + ); + + if (foundInMemoryConnector?.isSystemAction) { + throw Boom.badRequest( + i18n.translate('xpack.actions.serverSideErrors.systemActionUpdateForbidden', { + defaultMessage: 'System action {id} can not be updated.', + values: { + id, + }, + }) + ); + } + + if (foundInMemoryConnector?.isPreconfigured) { + throw new PreconfiguredActionDisabledModificationError( + i18n.translate('xpack.actions.serverSideErrors.predefinedActionUpdateDisabled', { + defaultMessage: 'Preconfigured action {id} can not be updated.', + values: { + id, + }, + }), + 'update' + ); + } + } catch (error) { + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.UPDATE, + savedObject: { type: 'action', id }, + error, + }) + ); + throw error; + } + const { attributes, references, version } = + await this.context.unsecuredSavedObjectsClient.get('action', id); + const { actionTypeId } = attributes; + const { name, config, secrets } = action; + const actionType = this.context.actionTypeRegistry.get(actionTypeId); + const configurationUtilities = this.context.actionTypeRegistry.getUtils(); + const validatedActionTypeConfig = validateConfig(actionType, config, { + configurationUtilities, + }); + const validatedActionTypeSecrets = validateSecrets(actionType, secrets, { + configurationUtilities, + }); + if (actionType.validate?.connector) { + validateConnector(actionType, { config, secrets }); + } + + this.context.actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); + + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.UPDATE, + savedObject: { type: 'action', id }, + outcome: 'unknown', + }) + ); + + const result = await this.context.unsecuredSavedObjectsClient.create( + 'action', + { + ...attributes, + actionTypeId, + name, + isMissingSecrets: false, + config: validatedActionTypeConfig as SavedObjectAttributes, + secrets: validatedActionTypeSecrets as SavedObjectAttributes, + }, + omitBy( + { + id, + overwrite: true, + references, + version, + }, + isUndefined + ) + ); + + try { + await this.context.connectorTokenClient.deleteConnectorTokens({ connectorId: id }); + } catch (e) { + this.context.logger.error( + `Failed to delete auth tokens for connector "${id}" after update: ${e.message}` + ); + } + + return { + id, + actionTypeId: result.attributes.actionTypeId as string, + isMissingSecrets: result.attributes.isMissingSecrets as boolean, + name: result.attributes.name as string, + config: result.attributes.config as Record, + isPreconfigured: false, + isSystemAction: false, + isDeprecated: isConnectorDeprecated(result.attributes), + }; + } + + /** + * Get an action + */ + public async get({ + id, + throwIfSystemAction = true, + }: { + id: string; + throwIfSystemAction?: boolean; + }): Promise { + try { + await this.context.authorization.ensureAuthorized({ operation: 'get' }); + } catch (error) { + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.GET, + savedObject: { type: 'action', id }, + error, + }) + ); + throw error; + } + + const foundInMemoryConnector = this.context.inMemoryConnectors.find( + (connector) => connector.id === id + ); + + /** + * Getting system connector is not allowed + * if throwIfSystemAction is set to true. + * Default behavior is to throw + */ + if ( + foundInMemoryConnector !== undefined && + foundInMemoryConnector.isSystemAction && + throwIfSystemAction + ) { + throw Boom.notFound(`Connector ${id} not found`); + } + + if (foundInMemoryConnector !== undefined) { + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.GET, + savedObject: { type: 'action', id }, + }) + ); + + return { + id, + actionTypeId: foundInMemoryConnector.actionTypeId, + name: foundInMemoryConnector.name, + isPreconfigured: foundInMemoryConnector.isPreconfigured, + isSystemAction: foundInMemoryConnector.isSystemAction, + isDeprecated: isConnectorDeprecated(foundInMemoryConnector), + }; + } + + const result = await this.context.unsecuredSavedObjectsClient.get('action', id); + + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.GET, + savedObject: { type: 'action', id }, + }) + ); + + return { + id, + actionTypeId: result.attributes.actionTypeId, + isMissingSecrets: result.attributes.isMissingSecrets, + name: result.attributes.name, + config: result.attributes.config, + isPreconfigured: false, + isSystemAction: false, + isDeprecated: isConnectorDeprecated(result.attributes), + }; + } + + /** + * Get all connectors with in-memory connectors + */ + public async getAll({ includeSystemActions = false } = {}): Promise { + return getAll({ context: this.context, includeSystemActions }); + } + + /** + * Get bulk actions with in-memory list + */ + public async getBulk({ + ids, + throwIfSystemAction = true, + }: { + ids: string[]; + throwIfSystemAction?: boolean; + }): Promise { + try { + await this.context.authorization.ensureAuthorized({ operation: 'get' }); + } catch (error) { + ids.forEach((id) => + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.GET, + savedObject: { type: 'action', id }, + error, + }) + ) + ); + throw error; + } + + const actionResults = new Array(); + + for (const actionId of ids) { + const action = this.context.inMemoryConnectors.find( + (inMemoryConnector) => inMemoryConnector.id === actionId + ); + + /** + * Getting system connector is not allowed + * if throwIfSystemAction is set to true. + * Default behavior is to throw + */ + if (action !== undefined && action.isSystemAction && throwIfSystemAction) { + throw Boom.notFound(`Connector ${action.id} not found`); + } + + if (action !== undefined) { + actionResults.push(action); + } + } + + // Fetch action objects in bulk + // Excluding in-memory actions to avoid an not found error, which is already added + const actionSavedObjectsIds = [ + ...new Set( + ids.filter( + (actionId) => !actionResults.find((actionResult) => actionResult.id === actionId) + ) + ), + ]; + + const bulkGetOpts = actionSavedObjectsIds.map((id) => ({ id, type: 'action' })); + const bulkGetResult = await this.context.unsecuredSavedObjectsClient.bulkGet( + bulkGetOpts + ); + + bulkGetResult.saved_objects.forEach(({ id, error }) => { + if (!error && this.context.auditLogger) { + this.context.auditLogger.log( + connectorAuditEvent({ + action: ConnectorAuditAction.GET, + savedObject: { type: 'action', id }, + }) + ); + } + }); + + for (const action of bulkGetResult.saved_objects) { + if (action.error) { + throw Boom.badRequest( + `Failed to load action ${action.id} (${action.error.statusCode}): ${action.error.message}` + ); + } + actionResults.push( + connectorFromSavedObject(action, isConnectorDeprecated(action.attributes)) + ); + } + + return actionResults; + } + + public async getOAuthAccessToken( + { type, options }: OAuthParams, + configurationUtilities: ActionsConfigurationUtilities + ) { + // Verify that user has edit access + await this.context.authorization.ensureAuthorized({ operation: 'update' }); + + // Verify that token url is allowed by allowed hosts config + try { + configurationUtilities.ensureUriAllowed(options.tokenUrl); + } catch (err) { + throw Boom.badRequest(err.message); + } + + // Verify that token url contains a hostname and uses https + const parsedUrl = url.parse( + options.tokenUrl, + false /* parseQueryString */, + true /* slashesDenoteHost */ + ); + + if (!parsedUrl.hostname) { + throw Boom.badRequest(`Token URL must contain hostname`); + } + + if (parsedUrl.protocol !== 'https:' && parsedUrl.protocol !== 'http:') { + throw Boom.badRequest(`Token URL must use http or https`); + } + + let accessToken: string | null = null; + if (type === 'jwt') { + const tokenOpts = options as OAuthJwtParams; + + try { + accessToken = await getOAuthJwtAccessToken({ + logger: this.context.logger, + configurationUtilities, + credentials: { + config: tokenOpts.config as GetOAuthJwtConfig, + secrets: tokenOpts.secrets as GetOAuthJwtSecrets, + }, + tokenUrl: tokenOpts.tokenUrl, + }); + + this.context.logger.debug( + `Successfully retrieved access token using JWT OAuth with tokenUrl ${ + tokenOpts.tokenUrl + } and config ${JSON.stringify(tokenOpts.config)}` + ); + } catch (err) { + this.context.logger.debug( + `Failed to retrieve access token using JWT OAuth with tokenUrl ${ + tokenOpts.tokenUrl + } and config ${JSON.stringify(tokenOpts.config)} - ${err.message}` + ); + throw Boom.badRequest(`Failed to retrieve access token`); + } + } else if (type === 'client') { + const tokenOpts = options as OAuthClientCredentialsParams; + try { + accessToken = await getOAuthClientCredentialsAccessToken({ + logger: this.context.logger, + configurationUtilities, + credentials: { + config: tokenOpts.config as GetOAuthClientCredentialsConfig, + secrets: tokenOpts.secrets as GetOAuthClientCredentialsSecrets, + }, + tokenUrl: tokenOpts.tokenUrl, + oAuthScope: tokenOpts.scope, + }); + + this.context.logger.debug( + `Successfully retrieved access token using Client Credentials OAuth with tokenUrl ${ + tokenOpts.tokenUrl + }, scope ${tokenOpts.scope} and config ${JSON.stringify(tokenOpts.config)}` + ); + } catch (err) { + this.context.logger.debug( + `Failed to retrieved access token using Client Credentials OAuth with tokenUrl ${ + tokenOpts.tokenUrl + }, scope ${tokenOpts.scope} and config ${JSON.stringify(tokenOpts.config)} - ${ + err.message + }` + ); + throw Boom.badRequest(`Failed to retrieve access token`); + } + } + + return { accessToken }; + } + + /** + * Delete action + */ + public async delete({ id }: { id: string }) { + try { + await this.context.authorization.ensureAuthorized({ operation: 'delete' }); + + const foundInMemoryConnector = this.context.inMemoryConnectors.find( + (connector) => connector.id === id + ); + + if (foundInMemoryConnector?.isSystemAction) { + throw Boom.badRequest( + i18n.translate('xpack.actions.serverSideErrors.systemActionDeletionForbidden', { + defaultMessage: 'System action {id} is not allowed to delete.', + values: { + id, + }, + }) + ); + } + + if (foundInMemoryConnector?.isPreconfigured) { + throw new PreconfiguredActionDisabledModificationError( + i18n.translate('xpack.actions.serverSideErrors.predefinedActionDeleteDisabled', { + defaultMessage: 'Preconfigured action {id} is not allowed to delete.', + values: { + id, + }, + }), + 'delete' + ); + } + } catch (error) { + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.DELETE, + savedObject: { type: 'action', id }, + error, + }) + ); + throw error; + } + + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.DELETE, + outcome: 'unknown', + savedObject: { type: 'action', id }, + }) + ); + + try { + await this.context.connectorTokenClient.deleteConnectorTokens({ connectorId: id }); + } catch (e) { + this.context.logger.error( + `Failed to delete auth tokens for connector "${id}" after delete: ${e.message}` + ); + } + + return await this.context.unsecuredSavedObjectsClient.delete('action', id); + } + + private getSystemActionKibanaPrivileges(connectorId: string, params?: ExecuteOptions['params']) { + const inMemoryConnector = this.context.inMemoryConnectors.find( + (connector) => connector.id === connectorId + ); + + const additionalPrivileges = inMemoryConnector?.isSystemAction + ? this.context.actionTypeRegistry.getSystemActionKibanaPrivileges( + inMemoryConnector.actionTypeId, + params + ) + : []; + + return additionalPrivileges; + } + + public async execute({ + actionId, + params, + source, + relatedSavedObjects, + }: Omit): Promise< + ActionTypeExecutorResult + > { + if ( + (await getAuthorizationModeBySource(this.context.unsecuredSavedObjectsClient, source)) === + AuthorizationMode.RBAC + ) { + const additionalPrivileges = this.getSystemActionKibanaPrivileges(actionId, params); + await this.context.authorization.ensureAuthorized({ + operation: 'execute', + additionalPrivileges, + }); + } else { + trackLegacyRBACExemption('execute', this.context.usageCounter); + } + + return this.context.actionExecutor.execute({ + actionId, + params, + source, + request: this.context.request, + relatedSavedObjects, + actionExecutionId: uuidv4(), + }); + } + + public async bulkEnqueueExecution(options: EnqueueExecutionOptions[]): Promise { + const sources: Array> = []; + options.forEach((option) => { + if (option.source) { + sources.push(option.source); + } + }); + + const authCounts = await getBulkAuthorizationModeBySource( + this.context.unsecuredSavedObjectsClient, + sources + ); + if (authCounts[AuthorizationMode.RBAC] > 0) { + /** + * 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' }); + } + if (authCounts[AuthorizationMode.Legacy] > 0) { + trackLegacyRBACExemption( + 'bulkEnqueueExecution', + this.context.usageCounter, + authCounts[AuthorizationMode.Legacy] + ); + } + return this.context.bulkExecutionEnqueuer(this.context.unsecuredSavedObjectsClient, options); + } + + public async ephemeralEnqueuedExecution(options: EnqueueExecutionOptions): Promise { + const { source } = options; + if ( + (await getAuthorizationModeBySource(this.context.unsecuredSavedObjectsClient, source)) === + AuthorizationMode.RBAC + ) { + await this.context.authorization.ensureAuthorized({ operation: 'execute' }); + } else { + trackLegacyRBACExemption('ephemeralEnqueuedExecution', this.context.usageCounter); + } + return this.context.ephemeralExecutionEnqueuer( + this.context.unsecuredSavedObjectsClient, + options + ); + } + + public async listTypes({ + featureId, + includeSystemActionTypes = false, + }: ListTypesParams = {}): Promise { + return listTypes(this.context, { featureId, includeSystemActionTypes }); + } + + public isActionTypeEnabled( + actionTypeId: string, + options: { notifyUsage: boolean } = { notifyUsage: false } + ) { + return this.context.actionTypeRegistry.isActionTypeEnabled(actionTypeId, options); + } + + public isPreconfigured(connectorId: string): boolean { + return !!this.context.inMemoryConnectors.find( + (connector) => connector.isPreconfigured && connector.id === connectorId + ); + } + + public isSystemAction(connectorId: string): boolean { + return !!this.context.inMemoryConnectors.find( + (connector) => connector.isSystemAction && connector.id === connectorId + ); + } + + public async getGlobalExecutionLogWithAuth({ + dateStart, + dateEnd, + filter, + page, + perPage, + sort, + namespaces, + }: GetGlobalExecutionLogParams): Promise { + this.context.logger.debug(`getGlobalExecutionLogWithAuth(): getting global execution log`); + + const authorizationTuple = {} as KueryNode; + try { + await this.context.authorization.ensureAuthorized({ operation: 'get' }); + } catch (error) { + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.GET_GLOBAL_EXECUTION_LOG, + error, + }) + ); + throw error; + } + + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.GET_GLOBAL_EXECUTION_LOG, + }) + ); + + const dateNow = new Date(); + const parsedDateStart = parseDate(dateStart, 'dateStart', dateNow); + const parsedDateEnd = parseDate(dateEnd, 'dateEnd', dateNow); + + const eventLogClient = await this.context.getEventLogClient(); + + try { + const aggResult = await eventLogClient.aggregateEventsWithAuthFilter( + 'action', + authorizationTuple, + { + start: parsedDateStart.toISOString(), + end: parsedDateEnd.toISOString(), + aggs: getExecutionLogAggregation({ + filter: filter ? `${filter} AND (${ACTION_FILTER})` : ACTION_FILTER, + page, + perPage, + sort, + }), + }, + namespaces, + true + ); + + return formatExecutionLogResult(aggResult); + } catch (err) { + this.context.logger.debug( + `actionsClient.getGlobalExecutionLogWithAuth(): error searching global event log: ${err.message}` + ); + throw err; + } + } + + public async getGlobalExecutionKpiWithAuth({ + dateStart, + dateEnd, + filter, + namespaces, + }: GetGlobalExecutionKPIParams) { + this.context.logger.debug(`getGlobalExecutionKpiWithAuth(): getting global execution KPI`); + + const authorizationTuple = {} as KueryNode; + try { + await this.context.authorization.ensureAuthorized({ operation: 'get' }); + } catch (error) { + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.GET_GLOBAL_EXECUTION_KPI, + error, + }) + ); + throw error; + } + + this.context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.GET_GLOBAL_EXECUTION_KPI, + }) + ); + + const dateNow = new Date(); + const parsedDateStart = parseDate(dateStart, 'dateStart', dateNow); + const parsedDateEnd = parseDate(dateEnd, 'dateEnd', dateNow); + + const eventLogClient = await this.context.getEventLogClient(); + + try { + const aggResult = await eventLogClient.aggregateEventsWithAuthFilter( + 'action', + authorizationTuple, + { + start: parsedDateStart.toISOString(), + end: parsedDateEnd.toISOString(), + aggs: getExecutionKPIAggregation( + filter ? `${filter} AND (${ACTION_FILTER})` : ACTION_FILTER + ), + }, + namespaces, + true + ); + + return formatExecutionKPIResult(aggResult); + } catch (err) { + this.context.logger.debug( + `actionsClient.getGlobalExecutionKpiWithAuth(): error searching global execution KPI: ${err.message}` + ); + throw err; + } + } +} diff --git a/x-pack/plugins/actions/server/actions_client/index.ts b/x-pack/plugins/actions/server/actions_client/index.ts new file mode 100644 index 0000000000000..b96ca83b402cc --- /dev/null +++ b/x-pack/plugins/actions/server/actions_client/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './actions_client'; diff --git a/x-pack/plugins/actions/server/application/connector/lib/connector_from_save_object.ts b/x-pack/plugins/actions/server/application/connector/lib/connector_from_save_object.ts new file mode 100644 index 0000000000000..95c158bff491b --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/lib/connector_from_save_object.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 { SavedObject } from '@kbn/core-saved-objects-common/src/server_types'; +import { RawAction } from '../../../types'; +import { Connector } from '../types'; + +export function connectorFromSavedObject( + savedObject: SavedObject, + isDeprecated: boolean +): Connector { + return { + id: savedObject.id, + ...savedObject.attributes, + isPreconfigured: false, + isDeprecated, + isSystemAction: false, + }; +} diff --git a/x-pack/plugins/actions/server/application/connector/lib/index.ts b/x-pack/plugins/actions/server/application/connector/lib/index.ts new file mode 100644 index 0000000000000..5cc0cb4a3dfda --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/lib/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export type { ConnectorWithOptionalDeprecation } from './is_connector_deprecated'; +export { isConnectorDeprecated } from './is_connector_deprecated'; +export { connectorFromSavedObject } from './connector_from_save_object'; diff --git a/x-pack/plugins/actions/server/lib/is_connector_deprecated.test.ts b/x-pack/plugins/actions/server/application/connector/lib/is_connector_deprecated.test.ts similarity index 100% rename from x-pack/plugins/actions/server/lib/is_connector_deprecated.test.ts rename to x-pack/plugins/actions/server/application/connector/lib/is_connector_deprecated.test.ts diff --git a/x-pack/plugins/actions/server/lib/is_connector_deprecated.ts b/x-pack/plugins/actions/server/application/connector/lib/is_connector_deprecated.ts similarity index 97% rename from x-pack/plugins/actions/server/lib/is_connector_deprecated.ts rename to x-pack/plugins/actions/server/application/connector/lib/is_connector_deprecated.ts index 4ebdeec7728eb..5946ed07bab74 100644 --- a/x-pack/plugins/actions/server/lib/is_connector_deprecated.ts +++ b/x-pack/plugins/actions/server/application/connector/lib/is_connector_deprecated.ts @@ -6,7 +6,7 @@ */ import { isPlainObject } from 'lodash'; -import { InMemoryConnector, RawAction } from '../types'; +import { RawAction, InMemoryConnector } from '../../../types'; export type ConnectorWithOptionalDeprecation = Omit & Pick, 'isDeprecated'>; 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 new file mode 100644 index 0000000000000..7e2ceb5b653c8 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/get_all/get_all.test.ts @@ -0,0 +1,553 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ActionsClient } from '../../../../actions_client'; +import { ActionsAuthorization } from '../../../../authorization/actions_authorization'; +import { connectorTokenClientMock } from '../../../../lib/connector_token_client.mock'; +import { getOAuthJwtAccessToken } from '../../../../lib/get_oauth_jwt_access_token'; +import { getOAuthClientCredentialsAccessToken } from '../../../../lib/get_oauth_client_credentials_access_token'; +import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks'; +import { actionsAuthorizationMock } from '../../../../authorization/actions_authorization.mock'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { actionExecutorMock } from '../../../../lib/action_executor.mock'; +import { httpServerMock } from '@kbn/core-http-server-mocks'; +import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; +import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; +import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { Logger } from '@kbn/logging'; +import { eventLogClientMock } from '@kbn/event-log-plugin/server/event_log_client.mock'; +import { ActionTypeRegistry } from '../../../../action_type_registry'; + +jest.mock('@kbn/core-saved-objects-utils-server', () => { + const actual = jest.requireActual('@kbn/core-saved-objects-utils-server'); + return { + ...actual, + SavedObjectsUtils: { + generateId: () => 'mock-saved-object-id', + }, + }; +}); + +jest.mock('../../../../lib/track_legacy_rbac_exemption', () => ({ + trackLegacyRBACExemption: jest.fn(), +})); + +jest.mock('../../../../authorization/get_authorization_mode_by_source', () => { + return { + getAuthorizationModeBySource: jest.fn(() => { + return 1; + }), + getBulkAuthorizationModeBySource: jest.fn(() => { + return 1; + }), + AuthorizationMode: { + Legacy: 0, + RBAC: 1, + }, + }; +}); + +jest.mock('../../../../lib/get_oauth_jwt_access_token', () => ({ + getOAuthJwtAccessToken: jest.fn(), +})); +jest.mock('../../../../lib/get_oauth_client_credentials_access_token', () => ({ + getOAuthClientCredentialsAccessToken: jest.fn(), +})); + +jest.mock('uuid', () => ({ + v4: () => 'uuidv4', +})); + +const kibanaIndices = ['.kibana']; +const unsecuredSavedObjectsClient = savedObjectsClientMock.create(); +const scopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); +const actionExecutor = actionExecutorMock.create(); +const authorization = actionsAuthorizationMock.create(); +const ephemeralExecutionEnqueuer = jest.fn(); +const bulkExecutionEnqueuer = jest.fn(); +const request = httpServerMock.createKibanaRequest(); +const auditLogger = auditLoggerMock.create(); +const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); +const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); +const logger = loggingSystemMock.create().get() as jest.Mocked; +const eventLogClient = eventLogClientMock.create(); +const getEventLogClient = jest.fn(); +const connectorTokenClient = connectorTokenClientMock.create(); + +let actionsClient: ActionsClient; +let actionTypeRegistry: ActionTypeRegistry; + +describe('getAll()', () => { + beforeEach(() => { + jest.resetAllMocks(); + actionsClient = new ActionsClient({ + logger, + actionTypeRegistry, + unsecuredSavedObjectsClient, + scopedClusterClient, + kibanaIndices, + inMemoryConnectors: [], + actionExecutor, + ephemeralExecutionEnqueuer, + bulkExecutionEnqueuer, + request, + authorization: authorization as unknown as ActionsAuthorization, + auditLogger, + usageCounter: mockUsageCounter, + connectorTokenClient, + getEventLogClient, + }); + (getOAuthJwtAccessToken as jest.Mock).mockResolvedValue(`Bearer jwttokentokentoken`); + (getOAuthClientCredentialsAccessToken as jest.Mock).mockResolvedValue( + `Bearer clienttokentokentoken` + ); + getEventLogClient.mockResolvedValue(eventLogClient); + }); + + describe('authorization', () => { + function getAllOperation(): ReturnType { + const expectedResult = { + total: 1, + per_page: 10, + page: 1, + saved_objects: [ + { + id: '1', + type: 'type', + attributes: { + name: 'test', + config: { + foo: 'bar', + }, + }, + score: 1, + references: [], + }, + ], + }; + unsecuredSavedObjectsClient.find.mockResolvedValueOnce(expectedResult); + scopedClusterClient.asInternalUser.search.mockResponse( + // @ts-expect-error not full search response + { + aggregations: { + '1': { doc_count: 6 }, + testPreconfigured: { doc_count: 2 }, + }, + } + ); + + actionsClient = new ActionsClient({ + logger, + actionTypeRegistry, + unsecuredSavedObjectsClient, + scopedClusterClient, + kibanaIndices, + actionExecutor, + ephemeralExecutionEnqueuer, + bulkExecutionEnqueuer, + request, + authorization: authorization as unknown as ActionsAuthorization, + inMemoryConnectors: [ + { + id: 'testPreconfigured', + actionTypeId: '.slack', + secrets: {}, + isPreconfigured: true, + isDeprecated: false, + isSystemAction: false, + name: 'test', + config: { + foo: 'bar', + }, + }, + ], + connectorTokenClient: connectorTokenClientMock.create(), + getEventLogClient, + }); + return actionsClient.getAll(); + } + + test('ensures user is authorised to get the type of action', async () => { + await getAllOperation(); + expect(authorization.ensureAuthorized).toHaveBeenCalledWith({ operation: 'get' }); + }); + + test('throws when user is not authorised to create the type of action', async () => { + authorization.ensureAuthorized.mockRejectedValue( + new Error(`Unauthorized to get all actions`) + ); + + await expect(getAllOperation()).rejects.toMatchInlineSnapshot( + `[Error: Unauthorized to get all actions]` + ); + + expect(authorization.ensureAuthorized).toHaveBeenCalledWith({ operation: 'get' }); + }); + }); + + describe('auditLogger', () => { + test('logs audit event when searching connectors', async () => { + unsecuredSavedObjectsClient.find.mockResolvedValueOnce({ + total: 1, + per_page: 10, + page: 1, + saved_objects: [ + { + id: '1', + type: 'type', + attributes: { + name: 'test', + isMissingSecrets: false, + config: { + foo: 'bar', + }, + }, + score: 1, + references: [], + }, + ], + }); + scopedClusterClient.asInternalUser.search.mockResponse( + // @ts-expect-error not full search response + { + aggregations: { + '1': { doc_count: 6 }, + testPreconfigured: { doc_count: 2 }, + }, + } + ); + + await actionsClient.getAll(); + + expect(auditLogger.log).toHaveBeenCalledWith( + expect.objectContaining({ + event: expect.objectContaining({ + action: 'connector_find', + outcome: 'success', + }), + kibana: { saved_object: { id: '1', type: 'action' } }, + }) + ); + }); + + test('logs audit event when not authorised to search connectors', async () => { + authorization.ensureAuthorized.mockRejectedValue(new Error('Unauthorized')); + + await expect(actionsClient.getAll()).rejects.toThrow(); + + expect(auditLogger.log).toHaveBeenCalledWith( + expect.objectContaining({ + event: expect.objectContaining({ + action: 'connector_find', + outcome: 'failure', + }), + error: { code: 'Error', message: 'Unauthorized' }, + }) + ); + }); + }); + + test('calls unsecuredSavedObjectsClient with parameters and returns inMemoryConnectors correctly', async () => { + const expectedResult = { + total: 1, + per_page: 10, + page: 1, + saved_objects: [ + { + id: '1', + type: 'type', + attributes: { + name: 'test', + isMissingSecrets: false, + config: { + foo: 'bar', + }, + }, + score: 1, + references: [], + }, + ], + }; + unsecuredSavedObjectsClient.find.mockResolvedValueOnce(expectedResult); + scopedClusterClient.asInternalUser.search.mockResponse( + // @ts-expect-error not full search response + { + aggregations: { + '1': { doc_count: 6 }, + testPreconfigured: { doc_count: 2 }, + 'system-connector-.cases': { doc_count: 2 }, + }, + } + ); + + actionsClient = new ActionsClient({ + logger, + actionTypeRegistry, + unsecuredSavedObjectsClient, + scopedClusterClient, + kibanaIndices, + actionExecutor, + ephemeralExecutionEnqueuer, + bulkExecutionEnqueuer, + request, + authorization: authorization as unknown as ActionsAuthorization, + inMemoryConnectors: [ + { + id: 'testPreconfigured', + actionTypeId: '.slack', + secrets: {}, + isPreconfigured: true, + isDeprecated: false, + isSystemAction: false, + name: 'test', + config: { + foo: 'bar', + }, + }, + /** + * System actions will not + * be returned from getAll + * if no options are provided + */ + { + id: 'system-connector-.cases', + actionTypeId: '.cases', + name: 'System action: .cases', + config: {}, + secrets: {}, + isDeprecated: false, + isMissingSecrets: false, + isPreconfigured: false, + isSystemAction: true, + }, + ], + connectorTokenClient: connectorTokenClientMock.create(), + getEventLogClient, + }); + + const result = await actionsClient.getAll(); + + expect(result).toEqual([ + { + id: '1', + name: 'test', + isMissingSecrets: false, + config: { foo: 'bar' }, + isPreconfigured: false, + isDeprecated: false, + isSystemAction: false, + referencedByCount: 6, + }, + { + id: 'testPreconfigured', + actionTypeId: '.slack', + name: 'test', + isPreconfigured: true, + isSystemAction: false, + isDeprecated: false, + referencedByCount: 2, + }, + ]); + }); + + test('get system actions correctly', async () => { + const expectedResult = { + total: 1, + per_page: 10, + page: 1, + saved_objects: [ + { + id: '1', + type: 'type', + attributes: { + name: 'test', + isMissingSecrets: false, + config: { + foo: 'bar', + }, + }, + score: 1, + references: [], + }, + ], + }; + unsecuredSavedObjectsClient.find.mockResolvedValueOnce(expectedResult); + scopedClusterClient.asInternalUser.search.mockResponse( + // @ts-expect-error not full search response + { + aggregations: { + '1': { doc_count: 6 }, + testPreconfigured: { doc_count: 2 }, + 'system-connector-.cases': { doc_count: 2 }, + }, + } + ); + + actionsClient = new ActionsClient({ + logger, + actionTypeRegistry, + unsecuredSavedObjectsClient, + scopedClusterClient, + kibanaIndices, + actionExecutor, + ephemeralExecutionEnqueuer, + bulkExecutionEnqueuer, + request, + authorization: authorization as unknown as ActionsAuthorization, + inMemoryConnectors: [ + { + id: 'testPreconfigured', + actionTypeId: '.slack', + secrets: {}, + isPreconfigured: true, + isDeprecated: false, + isSystemAction: false, + name: 'test', + config: { + foo: 'bar', + }, + }, + { + id: 'system-connector-.cases', + actionTypeId: '.cases', + name: 'System action: .cases', + config: {}, + secrets: {}, + isDeprecated: false, + isMissingSecrets: false, + isPreconfigured: false, + isSystemAction: true, + }, + ], + connectorTokenClient: connectorTokenClientMock.create(), + getEventLogClient, + }); + + const result = await actionsClient.getAll({ includeSystemActions: true }); + + expect(result).toEqual([ + { + actionTypeId: '.cases', + id: 'system-connector-.cases', + isDeprecated: false, + isPreconfigured: false, + isSystemAction: true, + name: 'System action: .cases', + referencedByCount: 2, + }, + { + id: '1', + name: 'test', + isMissingSecrets: false, + config: { foo: 'bar' }, + isPreconfigured: false, + isDeprecated: false, + isSystemAction: false, + referencedByCount: 6, + }, + { + id: 'testPreconfigured', + actionTypeId: '.slack', + name: 'test', + isPreconfigured: true, + isSystemAction: false, + isDeprecated: false, + referencedByCount: 2, + }, + ]); + }); + + test('validates connectors before return', async () => { + unsecuredSavedObjectsClient.find.mockResolvedValueOnce({ + total: 1, + per_page: 10, + page: 1, + saved_objects: [ + { + id: '1', + type: 'type', + attributes: { + name: 'test', + isMissingSecrets: false, + config: { + foo: 'bar', + }, + }, + score: 1, + references: [], + }, + ], + }); + scopedClusterClient.asInternalUser.search.mockResponse( + // @ts-expect-error not full search response + { + aggregations: { + '1': { doc_count: 6 }, + testPreconfigured: { doc_count: 2 }, + }, + } + ); + + actionsClient = new ActionsClient({ + logger, + actionTypeRegistry, + unsecuredSavedObjectsClient, + scopedClusterClient, + kibanaIndices, + actionExecutor, + ephemeralExecutionEnqueuer, + bulkExecutionEnqueuer, + request, + authorization: authorization as unknown as ActionsAuthorization, + inMemoryConnectors: [ + { + id: 'testPreconfigured', + actionTypeId: '.slack', + secrets: {}, + isPreconfigured: true, + isDeprecated: false, + isSystemAction: false, + name: 'test', + config: { + foo: 'bar', + }, + }, + ], + connectorTokenClient: connectorTokenClientMock.create(), + getEventLogClient, + }); + + const result = await actionsClient.getAll({ includeSystemActions: true }); + expect(result).toEqual([ + { + config: { + foo: 'bar', + }, + id: '1', + isDeprecated: false, + isMissingSecrets: false, + isPreconfigured: false, + isSystemAction: false, + name: 'test', + referencedByCount: 6, + }, + { + actionTypeId: '.slack', + id: 'testPreconfigured', + isDeprecated: false, + isPreconfigured: true, + isSystemAction: false, + name: 'test', + referencedByCount: 2, + }, + ]); + + expect(logger.warn).toHaveBeenCalledWith( + 'Error validating connector: 1, Error: [actionTypeId]: expected value of type [string] but got [undefined]' + ); + }); +}); diff --git a/x-pack/plugins/actions/server/application/connector/methods/get_all/get_all.ts b/x-pack/plugins/actions/server/application/connector/methods/get_all/get_all.ts new file mode 100644 index 0000000000000..f0945c27265c7 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/get_all/get_all.ts @@ -0,0 +1,129 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/** + * Get all actions with in-memory connectors + */ +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { connectorSchema } from '../../schemas'; +import { findConnectorsSo, searchConnectorsSo } from '../../../../data/connector'; +import { GetAllParams, InjectExtraFindDataParams } from './types'; +import { ConnectorAuditAction, connectorAuditEvent } from '../../../../lib/audit_events'; +import { connectorFromSavedObject, isConnectorDeprecated } from '../../lib'; +import { FindConnectorResult } from '../../types'; + +export async function getAll({ + context, + includeSystemActions = false, +}: GetAllParams): Promise { + try { + await context.authorization.ensureAuthorized({ operation: 'get' }); + } catch (error) { + context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.FIND, + error, + }) + ); + throw error; + } + + const savedObjectsActions = ( + await findConnectorsSo({ unsecuredSavedObjectsClient: context.unsecuredSavedObjectsClient }) + ).saved_objects.map((rawAction) => + connectorFromSavedObject(rawAction, isConnectorDeprecated(rawAction.attributes)) + ); + + savedObjectsActions.forEach(({ id }) => + context.auditLogger?.log( + connectorAuditEvent({ + action: ConnectorAuditAction.FIND, + savedObject: { type: 'action', id }, + }) + ) + ); + + const inMemoryConnectorsFiltered = includeSystemActions + ? context.inMemoryConnectors + : context.inMemoryConnectors.filter((connector) => !connector.isSystemAction); + + const mergedResult = [ + ...savedObjectsActions, + ...inMemoryConnectorsFiltered.map((inMemoryConnector) => ({ + id: inMemoryConnector.id, + actionTypeId: inMemoryConnector.actionTypeId, + name: inMemoryConnector.name, + isPreconfigured: inMemoryConnector.isPreconfigured, + isDeprecated: isConnectorDeprecated(inMemoryConnector), + isSystemAction: inMemoryConnector.isSystemAction, + })), + ].sort((a, b) => a.name.localeCompare(b.name)); + + mergedResult.forEach((connector) => { + // Try to validate the connectors, but don't throw. + try { + connectorSchema.validate(connector); + } catch (e) { + context.logger.warn(`Error validating connector: ${connector.id}, ${e}`); + } + }); + + return await injectExtraFindData({ + kibanaIndices: context.kibanaIndices, + scopedClusterClient: context.scopedClusterClient, + connectors: mergedResult, + }); +} + +async function injectExtraFindData({ + kibanaIndices, + scopedClusterClient, + connectors, +}: InjectExtraFindDataParams): Promise { + const aggs: Record = {}; + for (const connector of connectors) { + aggs[connector.id] = { + filter: { + bool: { + must: { + nested: { + path: 'references', + query: { + bool: { + filter: { + bool: { + must: [ + { + term: { + 'references.id': connector.id, + }, + }, + { + term: { + 'references.type': 'action', + }, + }, + ], + }, + }, + }, + }, + }, + }, + }, + }, + }; + } + + const aggregationResult = await searchConnectorsSo({ scopedClusterClient, kibanaIndices, aggs }); + + return connectors.map((connector) => ({ + ...connector, + // @ts-expect-error aggegation type is not specified + referencedByCount: aggregationResult.aggregations[connector.id].doc_count, + })); +} diff --git a/x-pack/plugins/actions/server/application/connector/methods/get_all/index.ts b/x-pack/plugins/actions/server/application/connector/methods/get_all/index.ts new file mode 100644 index 0000000000000..dcbc4c6fbc957 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/get_all/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 { getAll } from './get_all'; diff --git a/x-pack/plugins/actions/server/application/connector/methods/get_all/types/index.ts b/x-pack/plugins/actions/server/application/connector/methods/get_all/types/index.ts new file mode 100644 index 0000000000000..00354ca60714d --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/get_all/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 { GetAllParams, InjectExtraFindDataParams } from './params'; diff --git a/x-pack/plugins/actions/server/application/connector/methods/get_all/types/params.ts b/x-pack/plugins/actions/server/application/connector/methods/get_all/types/params.ts new file mode 100644 index 0000000000000..4e5157a1fdce0 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/get_all/types/params.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 { IScopedClusterClient } from '@kbn/core-elasticsearch-server'; +import { ActionsClientContext } from '../../../../../actions_client'; +import { Connector } from '../../../types'; + +export interface GetAllParams { + includeSystemActions?: boolean; + context: ActionsClientContext; +} + +export interface InjectExtraFindDataParams { + kibanaIndices: string[]; + scopedClusterClient: IScopedClusterClient; + connectors: Connector[]; +} diff --git a/x-pack/plugins/actions/server/application/connector/methods/list_types/index.ts b/x-pack/plugins/actions/server/application/connector/methods/list_types/index.ts new file mode 100644 index 0000000000000..e46209cd26fba --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/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 { 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/actions/server/application/connector/methods/list_types/schemas/list_types_params_schema.ts b/x-pack/plugins/actions/server/application/connector/methods/list_types/schemas/list_types_params_schema.ts new file mode 100644 index 0000000000000..848345c79ff31 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/methods/list_types/schemas/list_types_params_schema.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; + +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_schema.ts b/x-pack/plugins/actions/server/application/connector/schemas/connector_schema.ts new file mode 100644 index 0000000000000..0c2ac00c88d1e --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/schemas/connector_schema.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 { schema } from '@kbn/config-schema'; + +export const connectorSchema = schema.object({ + id: schema.string(), + name: schema.string(), + actionTypeId: schema.string(), + config: schema.maybe(schema.recordOf(schema.string(), schema.any())), + isMissingSecrets: schema.maybe(schema.boolean()), + isPreconfigured: schema.boolean(), + isDeprecated: schema.boolean(), + isSystemAction: schema.boolean(), +}); 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 new file mode 100644 index 0000000000000..b3cfc462c4208 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/schemas/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './connector_schema'; +export * from './connector_type_schema'; diff --git a/x-pack/plugins/actions/server/application/connector/types/connector.ts b/x-pack/plugins/actions/server/application/connector/types/connector.ts new file mode 100644 index 0000000000000..ef7b26ee9db29 --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/types/connector.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 { TypeOf } from '@kbn/config-schema'; +import { connectorSchema } from '../schemas'; +import { ActionTypeConfig } from '../../../types'; + +type ConnectorSchemaType = TypeOf; + +export interface Connector { + id: ConnectorSchemaType['id']; + actionTypeId: ConnectorSchemaType['actionTypeId']; + name: ConnectorSchemaType['name']; + isMissingSecrets?: ConnectorSchemaType['isMissingSecrets']; + config?: Config; + isPreconfigured: ConnectorSchemaType['isPreconfigured']; + isDeprecated: ConnectorSchemaType['isDeprecated']; + isSystemAction: ConnectorSchemaType['isSystemAction']; +} + +export interface FindConnectorResult extends Connector { + referencedByCount: number; +} 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 new file mode 100644 index 0000000000000..973513ec7b5cb --- /dev/null +++ b/x-pack/plugins/actions/server/application/connector/types/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 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/constants.ts b/x-pack/plugins/actions/server/data/connector/constants.ts new file mode 100644 index 0000000000000..6df87594b3568 --- /dev/null +++ b/x-pack/plugins/actions/server/data/connector/constants.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. + */ + +// We are assuming there won't be many actions. This is why we will load +// all the actions in advance and assume the total count to not go over 10000. +// We'll set this max setting assuming it's never reached. +export const MAX_ACTIONS_RETURNED = 10000; diff --git a/x-pack/plugins/actions/server/data/connector/find_connectors_so.ts b/x-pack/plugins/actions/server/data/connector/find_connectors_so.ts new file mode 100644 index 0000000000000..da232f5b2aa83 --- /dev/null +++ b/x-pack/plugins/actions/server/data/connector/find_connectors_so.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 { FindConnectorsSoResult, FindConnectorsSoParams } from './types'; +import { MAX_ACTIONS_RETURNED } from './constants'; + +export const findConnectorsSo = async ({ + unsecuredSavedObjectsClient, +}: FindConnectorsSoParams): Promise => { + return unsecuredSavedObjectsClient.find({ + perPage: MAX_ACTIONS_RETURNED, + type: 'action', + }); +}; diff --git a/x-pack/plugins/actions/server/data/connector/index.ts b/x-pack/plugins/actions/server/data/connector/index.ts new file mode 100644 index 0000000000000..c317e3c6227cd --- /dev/null +++ b/x-pack/plugins/actions/server/data/connector/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 { findConnectorsSo } from './find_connectors_so'; +export { searchConnectorsSo } from './search_connectors_so'; 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 new file mode 100644 index 0000000000000..09d3ae3b532d9 --- /dev/null +++ b/x-pack/plugins/actions/server/data/connector/search_connectors_so.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 { SearchConnectorsSoParams } from './types'; + +export const searchConnectorsSo = async ({ + scopedClusterClient, + kibanaIndices, + aggs, +}: SearchConnectorsSoParams) => { + return scopedClusterClient.asInternalUser.search({ + index: kibanaIndices, + ignore_unavailable: true, + body: { + aggs, + size: 0, + query: { + match_all: {}, + }, + }, + }); +}; diff --git a/x-pack/plugins/actions/server/data/connector/types/find_connectors_so_result.ts b/x-pack/plugins/actions/server/data/connector/types/find_connectors_so_result.ts new file mode 100644 index 0000000000000..ff1f3b0f89c9c --- /dev/null +++ b/x-pack/plugins/actions/server/data/connector/types/find_connectors_so_result.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 { SavedObjectsFindResponse } from '@kbn/core-saved-objects-api-server'; +import { RawAction } from '../../../types'; + +export type FindConnectorsSoResult = SavedObjectsFindResponse; diff --git a/x-pack/plugins/actions/server/data/connector/types/index.ts b/x-pack/plugins/actions/server/data/connector/types/index.ts new file mode 100644 index 0000000000000..070f10e48cf15 --- /dev/null +++ b/x-pack/plugins/actions/server/data/connector/types/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 type { SearchConnectorsSoParams, FindConnectorsSoParams } from './params'; +export type { FindConnectorsSoResult } from './find_connectors_so_result'; diff --git a/x-pack/plugins/actions/server/data/connector/types/params.ts b/x-pack/plugins/actions/server/data/connector/types/params.ts new file mode 100644 index 0000000000000..c92aaf2f87fd0 --- /dev/null +++ b/x-pack/plugins/actions/server/data/connector/types/params.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 { IScopedClusterClient } from '@kbn/core-elasticsearch-server'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; + +export interface SearchConnectorsSoParams { + kibanaIndices: string[]; + scopedClusterClient: IScopedClusterClient; + aggs: Record; +} + +export interface FindConnectorsSoParams { + unsecuredSavedObjectsClient: SavedObjectsClientContract; +} diff --git a/x-pack/plugins/actions/server/index.ts b/x-pack/plugins/actions/server/index.ts index 3deddfc9c16c6..082c266fa00e3 100644 --- a/x-pack/plugins/actions/server/index.ts +++ b/x-pack/plugins/actions/server/index.ts @@ -24,9 +24,10 @@ export type { ActionType, InMemoryConnector, ActionsApiRequestHandlerContext, - FindActionResult, } from './types'; +export type { FindConnectorResult as FindActionResult } from './application/connector/types'; + export type { PluginSetupContract, PluginStartContract } from './plugin'; export { 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.test.ts b/x-pack/plugins/actions/server/plugin.test.ts index 6752f85e9a464..66d75da5fd7cf 100644 --- a/x-pack/plugins/actions/server/plugin.test.ts +++ b/x-pack/plugins/actions/server/plugin.test.ts @@ -237,7 +237,7 @@ describe('Actions Plugin', () => { * that got set up on start (step 3). */ // @ts-expect-error: inMemoryConnectors can be accessed - expect(actionsContextHandler.getActionsClient().inMemoryConnectors).toEqual([ + expect(actionsContextHandler.getActionsClient().context.inMemoryConnectors).toEqual([ { id: 'preconfiguredServerLog', actionTypeId: '.server-log', diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index a9c70ec192f57..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'; @@ -96,7 +95,7 @@ import { InMemoryMetrics, registerClusterCollector, registerNodeCollector } from import { isConnectorDeprecated, ConnectorWithOptionalDeprecation, -} from './lib/is_connector_deprecated'; +} from './application/connector/lib'; import { createSubActionConnectorFramework } from './sub_action_framework'; import { IServiceAbstract, SubActionConnectorType } from './sub_action_framework/types'; import { SubActionConnector } from './sub_action_framework/sub_action_connector'; @@ -443,12 +442,6 @@ export class ActionsPlugin implements Plugin ({ + verifyAccessAndContext: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); + (verifyAccessAndContext as jest.Mock).mockImplementation((license, handler) => handler); +}); + +describe('getAllConnectorsRoute', () => { + it('get all connectors with proper parameters', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + getAllConnectorsRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/actions/connectors"`); + + const actionsClient = actionsClientMock.create(); + actionsClient.getAll.mockResolvedValueOnce([]); + + const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Array [], + } + `); + + expect(actionsClient.getAll).toHaveBeenCalledTimes(1); + + expect(res.ok).toHaveBeenCalledWith({ + body: [], + }); + }); + + it('ensures the license allows getting all connectors', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + getAllConnectorsRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/actions/connectors"`); + + const actionsClient = actionsClientMock.create(); + actionsClient.getAll.mockResolvedValueOnce([]); + + const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']); + + await handler(context, req, res); + + expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function)); + }); + + it('ensures the license check prevents getting all connectors', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + (verifyAccessAndContext as jest.Mock).mockImplementation(() => async () => { + throw new Error('OMG'); + }); + + getAllConnectorsRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/actions/connectors"`); + + const actionsClient = actionsClientMock.create(); + actionsClient.getAll.mockResolvedValueOnce([]); + + const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']); + + expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + + expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function)); + }); +}); diff --git a/x-pack/plugins/actions/server/routes/connector/get_all/get_all.ts b/x-pack/plugins/actions/server/routes/connector/get_all/get_all.ts new file mode 100644 index 0000000000000..068ce777647b4 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/get_all/get_all.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 { IRouter } from '@kbn/core/server'; +import { ConnectorResponseV1 } from '../../../../common/routes/connector/response'; +import { transformGetAllConnectorsResponseV1 } 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 getAllConnectorsRoute = ( + router: IRouter, + licenseState: ILicenseState +) => { + router.get( + { + path: `${BASE_ACTION_API_PATH}/connectors`, + validate: {}, + }, + router.handleLegacyErrors( + verifyAccessAndContext(licenseState, async function (context, req, res) { + const actionsClient = (await context.actions).getActionsClient(); + const result = await actionsClient.getAll(); + + const responseBody: ConnectorResponseV1[] = transformGetAllConnectorsResponseV1(result); + return res.ok({ body: responseBody }); + }) + ) + ); +}; diff --git a/x-pack/plugins/actions/server/routes/connector/get_all/index.ts b/x-pack/plugins/actions/server/routes/connector/get_all/index.ts new file mode 100644 index 0000000000000..58680a84850b2 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/get_all/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 { getAllConnectorsRoute } from './get_all'; diff --git a/x-pack/plugins/actions/server/routes/connector/get_all/transforms/index.ts b/x-pack/plugins/actions/server/routes/connector/get_all/transforms/index.ts new file mode 100644 index 0000000000000..e989acda56cce --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/get_all/transforms/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { transformGetAllConnectorsResponse } from './transform_connectors_response/latest'; + +export { transformGetAllConnectorsResponse as transformGetAllConnectorsResponseV1 } from './transform_connectors_response/v1'; diff --git a/x-pack/plugins/actions/server/routes/connector/get_all/transforms/transform_connectors_response/latest.ts b/x-pack/plugins/actions/server/routes/connector/get_all/transforms/transform_connectors_response/latest.ts new file mode 100644 index 0000000000000..500cc1435aadb --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/get_all/transforms/transform_connectors_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 { transformGetAllConnectorsResponse } from './v1'; diff --git a/x-pack/plugins/actions/server/routes/connector/get_all/transforms/transform_connectors_response/v1.ts b/x-pack/plugins/actions/server/routes/connector/get_all/transforms/transform_connectors_response/v1.ts new file mode 100644 index 0000000000000..731726560eb0c --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/get_all/transforms/transform_connectors_response/v1.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FindConnectorResult } from '../../../../../application/connector/types'; +import { ConnectorResponseV1 } from '../../../../../../common/routes/connector/response'; + +export const transformGetAllConnectorsResponse = ( + results: FindConnectorResult[] +): ConnectorResponseV1[] => { + return results.map( + ({ + id, + name, + config, + actionTypeId, + isPreconfigured, + isDeprecated, + referencedByCount, + isMissingSecrets, + isSystemAction, + }) => ({ + id, + name, + config, + connector_type_id: actionTypeId, + is_preconfigured: isPreconfigured, + is_deprecated: isDeprecated, + referenced_by_count: referencedByCount, + is_missing_secrets: isMissingSecrets, + is_system_action: isSystemAction, + }) + ); +}; 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/list_types/list_types.test.ts b/x-pack/plugins/actions/server/routes/connector/list_types/list_types.test.ts new file mode 100644 index 0000000000000..91419ac562324 --- /dev/null +++ b/x-pack/plugins/actions/server/routes/connector/list_types/list_types.test.ts @@ -0,0 +1,248 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { httpServiceMock } from '@kbn/core/server/mocks'; +import { LicenseType } from '@kbn/licensing-plugin/server'; +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', () => ({ + verifyAccessAndContext: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); + (verifyAccessAndContext as jest.Mock).mockImplementation((license, handler) => handler); +}); + +describe('listTypesRoute', () => { + it('lists action types with proper parameters', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + listTypesRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/actions/connector_types"`); + + const listTypes = [ + { + id: '1', + name: 'name', + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + minimumLicenseRequired: 'gold' as LicenseType, + supportedFeatureIds: ['alerting'], + isSystemActionType: false, + }, + ]; + + const actionsClient = actionsClientMock.create(); + actionsClient.listTypes.mockResolvedValueOnce(listTypes); + const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Array [ + Object { + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "id": "1", + "is_system_action_type": false, + "minimum_license_required": "gold", + "name": "name", + "supported_feature_ids": Array [ + "alerting", + ], + }, + ], + } + `); + + expect(res.ok).toHaveBeenCalledWith({ + body: [ + { + id: '1', + name: 'name', + enabled: true, + enabled_in_config: true, + enabled_in_license: true, + supported_feature_ids: ['alerting'], + minimum_license_required: 'gold', + is_system_action_type: false, + }, + ], + }); + }); + + it('passes feature_id if provided as query parameter', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + listTypesRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/actions/connector_types"`); + + const listTypes = [ + { + id: '1', + name: 'name', + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + supportedFeatureIds: ['alerting'], + minimumLicenseRequired: 'gold' as LicenseType, + isSystemActionType: false, + }, + ]; + + const actionsClient = actionsClientMock.create(); + actionsClient.listTypes.mockResolvedValueOnce(listTypes); + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + query: { + feature_id: 'alerting', + }, + }, + ['ok'] + ); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Array [ + Object { + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "id": "1", + "is_system_action_type": false, + "minimum_license_required": "gold", + "name": "name", + "supported_feature_ids": Array [ + "alerting", + ], + }, + ], + } + `); + + expect(actionsClient.listTypes).toHaveBeenCalledTimes(1); + expect(actionsClient.listTypes.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "featureId": "alerting", + }, + ] + `); + + expect(res.ok).toHaveBeenCalledWith({ + body: [ + { + id: '1', + name: 'name', + enabled: true, + enabled_in_config: true, + enabled_in_license: true, + supported_feature_ids: ['alerting'], + minimum_license_required: 'gold', + is_system_action_type: false, + }, + ], + }); + }); + + it('ensures the license allows listing action types', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + listTypesRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/actions/connector_types"`); + + const listTypes = [ + { + id: '1', + name: 'name', + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + supportedFeatureIds: ['alerting'], + minimumLicenseRequired: 'gold' as LicenseType, + isSystemActionType: false, + }, + ]; + + const actionsClient = actionsClientMock.create(); + actionsClient.listTypes.mockResolvedValueOnce(listTypes); + + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + params: { id: '1' }, + }, + ['ok'] + ); + + await handler(context, req, res); + + expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function)); + }); + + it('ensures the license check prevents listing action types', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + (verifyAccessAndContext as jest.Mock).mockImplementation(() => async () => { + throw new Error('OMG'); + }); + + listTypesRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/actions/connector_types"`); + + const listTypes = [ + { + id: '1', + name: 'name', + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + supportedFeatureIds: ['alerting'], + minimumLicenseRequired: 'gold' as LicenseType, + isSystemActionType: false, + }, + ]; + + const actionsClient = actionsClientMock.create(); + actionsClient.listTypes.mockResolvedValueOnce(listTypes); + + const [context, req, res] = mockHandlerArguments( + { actionsClient }, + { + params: { id: '1' }, + }, + ['ok'] + ); + + expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); + + expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function)); + }); +}); 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.test.ts b/x-pack/plugins/actions/server/routes/connector_types.test.ts deleted file mode 100644 index 4c5a7089b75c4..0000000000000 --- a/x-pack/plugins/actions/server/routes/connector_types.test.ts +++ /dev/null @@ -1,248 +0,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 { 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'; - -jest.mock('./verify_access_and_context', () => ({ - verifyAccessAndContext: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); - (verifyAccessAndContext as jest.Mock).mockImplementation((license, handler) => handler); -}); - -describe('connectorTypesRoute', () => { - it('lists action types with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - connectorTypesRoute(router, licenseState); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/actions/connector_types"`); - - const listTypes = [ - { - id: '1', - name: 'name', - enabled: true, - enabledInConfig: true, - enabledInLicense: true, - minimumLicenseRequired: 'gold' as LicenseType, - supportedFeatureIds: ['alerting'], - isSystemActionType: false, - }, - ]; - - const actionsClient = actionsClientMock.create(); - actionsClient.listTypes.mockResolvedValueOnce(listTypes); - const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Array [ - Object { - "enabled": true, - "enabled_in_config": true, - "enabled_in_license": true, - "id": "1", - "is_system_action_type": false, - "minimum_license_required": "gold", - "name": "name", - "supported_feature_ids": Array [ - "alerting", - ], - }, - ], - } - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: [ - { - id: '1', - name: 'name', - enabled: true, - enabled_in_config: true, - enabled_in_license: true, - supported_feature_ids: ['alerting'], - minimum_license_required: 'gold', - is_system_action_type: false, - }, - ], - }); - }); - - it('passes feature_id if provided as query parameter', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - connectorTypesRoute(router, licenseState); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/actions/connector_types"`); - - const listTypes = [ - { - id: '1', - name: 'name', - enabled: true, - enabledInConfig: true, - enabledInLicense: true, - supportedFeatureIds: ['alerting'], - minimumLicenseRequired: 'gold' as LicenseType, - isSystemActionType: false, - }, - ]; - - const actionsClient = actionsClientMock.create(); - actionsClient.listTypes.mockResolvedValueOnce(listTypes); - const [context, req, res] = mockHandlerArguments( - { actionsClient }, - { - query: { - feature_id: 'alerting', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Array [ - Object { - "enabled": true, - "enabled_in_config": true, - "enabled_in_license": true, - "id": "1", - "is_system_action_type": false, - "minimum_license_required": "gold", - "name": "name", - "supported_feature_ids": Array [ - "alerting", - ], - }, - ], - } - `); - - expect(actionsClient.listTypes).toHaveBeenCalledTimes(1); - expect(actionsClient.listTypes.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "featureId": "alerting", - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: [ - { - id: '1', - name: 'name', - enabled: true, - enabled_in_config: true, - enabled_in_license: true, - supported_feature_ids: ['alerting'], - minimum_license_required: 'gold', - is_system_action_type: false, - }, - ], - }); - }); - - it('ensures the license allows listing action types', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - connectorTypesRoute(router, licenseState); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/actions/connector_types"`); - - const listTypes = [ - { - id: '1', - name: 'name', - enabled: true, - enabledInConfig: true, - enabledInLicense: true, - supportedFeatureIds: ['alerting'], - minimumLicenseRequired: 'gold' as LicenseType, - isSystemActionType: false, - }, - ]; - - const actionsClient = actionsClientMock.create(); - actionsClient.listTypes.mockResolvedValueOnce(listTypes); - - const [context, req, res] = mockHandlerArguments( - { actionsClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function)); - }); - - it('ensures the license check prevents listing action types', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyAccessAndContext as jest.Mock).mockImplementation(() => async () => { - throw new Error('OMG'); - }); - - connectorTypesRoute(router, licenseState); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/actions/connector_types"`); - - const listTypes = [ - { - id: '1', - name: 'name', - enabled: true, - enabledInConfig: true, - enabledInLicense: true, - supportedFeatureIds: ['alerting'], - minimumLicenseRequired: 'gold' as LicenseType, - isSystemActionType: false, - }, - ]; - - const actionsClient = actionsClientMock.create(); - actionsClient.listTypes.mockResolvedValueOnce(listTypes); - - const [context, req, res] = mockHandlerArguments( - { actionsClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function)); - }); -}); 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_all.test.ts b/x-pack/plugins/actions/server/routes/get_all.test.ts deleted file mode 100644 index ea65a3bdf4dd1..0000000000000 --- a/x-pack/plugins/actions/server/routes/get_all.test.ts +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getAllActionRoute } from './get_all'; -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'; - -jest.mock('./verify_access_and_context', () => ({ - verifyAccessAndContext: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); - (verifyAccessAndContext as jest.Mock).mockImplementation((license, handler) => handler); -}); - -describe('getAllActionRoute', () => { - it('get all actions with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAllActionRoute(router, licenseState); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/actions/connectors"`); - - const actionsClient = actionsClientMock.create(); - actionsClient.getAll.mockResolvedValueOnce([]); - - const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Array [], - } - `); - - expect(actionsClient.getAll).toHaveBeenCalledTimes(1); - - expect(res.ok).toHaveBeenCalledWith({ - body: [], - }); - }); - - it('ensures the license allows getting all actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAllActionRoute(router, licenseState); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/actions/connectors"`); - - const actionsClient = actionsClientMock.create(); - actionsClient.getAll.mockResolvedValueOnce([]); - - const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']); - - await handler(context, req, res); - - expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function)); - }); - - it('ensures the license check prevents getting all actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyAccessAndContext as jest.Mock).mockImplementation(() => async () => { - throw new Error('OMG'); - }); - - getAllActionRoute(router, licenseState); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/actions/connectors"`); - - const actionsClient = actionsClientMock.create(); - actionsClient.getAll.mockResolvedValueOnce([]); - - const [context, req, res] = mockHandlerArguments({ actionsClient }, {}, ['ok']); - - expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyAccessAndContext).toHaveBeenCalledWith(licenseState, expect.any(Function)); - }); -}); diff --git a/x-pack/plugins/actions/server/routes/get_all.ts b/x-pack/plugins/actions/server/routes/get_all.ts deleted file mode 100644 index dec70257313e1..0000000000000 --- a/x-pack/plugins/actions/server/routes/get_all.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { IRouter } from '@kbn/core/server'; -import { ILicenseState } from '../lib'; -import { BASE_ACTION_API_PATH, RewriteResponseCase } from '../../common'; -import { ActionsRequestHandlerContext, FindActionResult } from '../types'; -import { verifyAccessAndContext } from './verify_access_and_context'; - -const rewriteBodyRes: RewriteResponseCase = (results) => { - return results.map( - ({ - actionTypeId, - isPreconfigured, - isDeprecated, - referencedByCount, - isMissingSecrets, - isSystemAction, - ...res - }) => ({ - ...res, - connector_type_id: actionTypeId, - is_preconfigured: isPreconfigured, - is_deprecated: isDeprecated, - referenced_by_count: referencedByCount, - is_missing_secrets: isMissingSecrets, - is_system_action: isSystemAction, - }) - ); -}; - -export const getAllActionRoute = ( - router: IRouter, - licenseState: ILicenseState -) => { - router.get( - { - path: `${BASE_ACTION_API_PATH}/connectors`, - validate: {}, - }, - router.handleLegacyErrors( - verifyAccessAndContext(licenseState, async function (context, req, res) { - const actionsClient = (await context.actions).getActionsClient(); - const result = await actionsClient.getAll(); - return res.ok({ - body: rewriteBodyRes(result), - }); - }) - ) - ); -}; 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 90704190adb9c..e5dce0ac3b6c7 100644 --- a/x-pack/plugins/actions/server/routes/index.ts +++ b/x-pack/plugins/actions/server/routes/index.ts @@ -7,14 +7,14 @@ 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 { getAllActionRoute } from './get_all'; -import { connectorTypesRoute } from './connector_types'; import { updateActionRoute } from './update'; import { getOAuthAccessToken } from './get_oauth_access_token'; import { defineLegacyRoutes } from './legacy'; @@ -37,9 +37,9 @@ export function defineRoutes(opts: RouteOptions) { createActionRoute(router, licenseState); deleteActionRoute(router, licenseState); getActionRoute(router, licenseState); - getAllActionRoute(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/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index a20ea31eeea54..91c6e0060cb67 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -35,6 +35,7 @@ export type ActionTypeParams = Record; export type ConnectorTokenClientContract = PublicMethodsOf; import type { ActionExecutionSource } from './lib'; +import { Connector, FindConnectorResult } from './application/connector/types'; export type { ActionExecutionSource } from './lib'; export { ActionExecutionSourceType } from './lib'; @@ -77,16 +78,7 @@ export interface ActionTypeExecutorOptions< source?: ActionExecutionSource; } -export interface ActionResult { - id: string; - actionTypeId: string; - name: string; - isMissingSecrets?: boolean; - config?: Config; - isPreconfigured: boolean; - isDeprecated: boolean; - isSystemAction: boolean; -} +export type ActionResult = Connector; export interface InMemoryConnector< Config extends ActionTypeConfig = ActionTypeConfig, @@ -96,9 +88,7 @@ export interface InMemoryConnector< config: Config; } -export interface FindActionResult extends ActionResult { - referencedByCount: number; -} +export type FindActionResult = FindConnectorResult; // signature of the action type executor function export type ExecutorType< diff --git a/x-pack/plugins/actions/tsconfig.json b/x-pack/plugins/actions/tsconfig.json index ac252d3362d21..0f4d2faf03e1a 100644 --- a/x-pack/plugins/actions/tsconfig.json +++ b/x-pack/plugins/actions/tsconfig.json @@ -39,6 +39,10 @@ "@kbn/core-saved-objects-api-server", "@kbn/core-elasticsearch-server", "@kbn/core-http-router-server-internal", + "@kbn/core-saved-objects-common", + "@kbn/core-saved-objects-api-server-mocks", + "@kbn/core-elasticsearch-server-mocks", + "@kbn/core-logging-server-mocks", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx index 0e5c23ac21010..dd2380fedfa32 100644 --- a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx +++ b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx @@ -18,7 +18,6 @@ import { UrlStateProvider } from '@kbn/ml-url-state'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { DatePickerContextProvider, mlTimefilterRefresh$ } from '@kbn/ml-date-picker'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; -import { toMountPoint, wrapWithTheme } from '@kbn/kibana-react-plugin/public'; import { type Observable } from 'rxjs'; import { DataSourceContext } from '../../hooks/use_data_source'; @@ -55,9 +54,7 @@ export const ChangePointDetectionAppState: FC appDependencies, }) => { const datePickerDeps = { - ...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings']), - toMountPoint, - wrapWithTheme, + ...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']), uiSettingsKeys: UI_SETTINGS, }; diff --git a/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx b/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx index ab52ab99266f3..a7c9bc17b6fe9 100644 --- a/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx +++ b/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx @@ -14,7 +14,6 @@ import { UrlStateProvider } from '@kbn/ml-url-state'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { DatePickerContextProvider } from '@kbn/ml-date-picker'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; -import { toMountPoint, wrapWithTheme } from '@kbn/kibana-react-plugin/public'; import { DataSourceContext } from '../../hooks/use_data_source'; import type { AiopsAppDependencies } from '../../hooks/use_aiops_app_context'; @@ -52,9 +51,7 @@ export const LogCategorizationAppState: FC = ({ } const datePickerDeps = { - ...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings']), - toMountPoint, - wrapWithTheme, + ...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']), uiSettingsKeys: UI_SETTINGS, }; diff --git a/x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx b/x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx index 16ef28ef75fc0..5890bd8a2f74d 100644 --- a/x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx +++ b/x-pack/plugins/aiops/public/components/log_categorization/show_flyout.tsx @@ -12,14 +12,11 @@ import { pick } from 'lodash'; import type { CoreStart } from '@kbn/core/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; -import { - toMountPoint, - wrapWithTheme, - KibanaContextProvider, -} from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { toMountPoint } from '@kbn/react-kibana-mount'; import type { DataViewField, DataView } from '@kbn/data-views-plugin/common'; import { UI_SETTINGS } from '@kbn/data-plugin/public'; -import { DatePickerContextProvider } from '@kbn/ml-date-picker'; +import { DatePickerContextProvider, type DatePickerDependencies } from '@kbn/ml-date-picker'; import { StorageContextProvider } from '@kbn/ml-local-storage'; import type { AiopsPluginStartDeps } from '../../types'; import { AiopsAppContext } from '../../hooks/use_aiops_app_context'; @@ -34,7 +31,7 @@ export async function showCategorizeFlyout( coreStart: CoreStart, plugins: AiopsPluginStartDeps ): Promise { - const { http, theme, overlays, application, notifications, uiSettings } = coreStart; + const { http, theme, overlays, application, notifications, uiSettings, i18n } = coreStart; return new Promise(async (resolve, reject) => { try { @@ -49,38 +46,36 @@ export async function showCategorizeFlyout( http, theme, application, + i18n, ...plugins, }; - const datePickerDeps = { + const datePickerDeps: DatePickerDependencies = { ...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings']), - toMountPoint, - wrapWithTheme, + i18n, uiSettingsKeys: UI_SETTINGS, }; const flyoutSession = overlays.openFlyout( toMountPoint( - wrapWithTheme( - - - - - - - - - , - theme.theme$ - ) + + + + + + + + + , + { theme, i18n } ), { 'data-test-subj': 'aiopsCategorizeFlyout', 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/components/log_rate_analysis/log_rate_analysis_app_state.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_app_state.tsx index 1bbca85e83e09..212d0465b9cc0 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_app_state.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_app_state.tsx @@ -15,7 +15,6 @@ import { UrlStateProvider } from '@kbn/ml-url-state'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { DatePickerContextProvider } from '@kbn/ml-date-picker'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; -import { toMountPoint, wrapWithTheme } from '@kbn/kibana-react-plugin/public'; import type { AiopsAppDependencies } from '../../hooks/use_aiops_app_context'; import { AiopsAppContext } from '../../hooks/use_aiops_app_context'; @@ -58,9 +57,7 @@ export const LogRateAnalysisAppState: FC = ({ } const datePickerDeps = { - ...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings']), - toMountPoint, - wrapWithTheme, + ...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']), uiSettingsKeys: UI_SETTINGS, }; diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx index 80babf7530d02..ec258081d840d 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper.tsx @@ -18,7 +18,6 @@ import { UrlStateProvider } from '@kbn/ml-url-state'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { DatePickerContextProvider } from '@kbn/ml-date-picker'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; -import { toMountPoint, wrapWithTheme } from '@kbn/kibana-react-plugin/public'; import { timeSeriesDataViewWarning } from '../../../application/utils/time_series_dataview_check'; import { AiopsAppContext, type AiopsAppDependencies } from '../../../hooks/use_aiops_app_context'; @@ -81,9 +80,7 @@ export const LogRateAnalysisContentWrapper: FC this.setInitializationFinished()); + } + + private async initOutput() { + const { + data: { dataViews: dataViewsService }, + } = this.deps; + + const { dataViewId } = this.getInput(); + + const dataView = await dataViewsService.get(dataViewId); + + this.updateOutput({ + indexPatterns: [dataView], + }); } public reportsEmbeddableLoad() { @@ -95,9 +114,7 @@ export class EmbeddableChangePointChart extends AbstractEmbeddable< const I18nContext = this.deps.i18n.Context; const datePickerDeps = { - ...pick(this.deps, ['data', 'http', 'notifications', 'theme', 'uiSettings']), - toMountPoint, - wrapWithTheme, + ...pick(this.deps, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']), uiSettingsKeys: UI_SETTINGS, }; diff --git a/x-pack/plugins/aiops/public/embeddable/embeddable_chart_component_wrapper.tsx b/x-pack/plugins/aiops/public/embeddable/embeddable_chart_component_wrapper.tsx index 3cc8a6d6e47a0..54ed702eadf63 100644 --- a/x-pack/plugins/aiops/public/embeddable/embeddable_chart_component_wrapper.tsx +++ b/x-pack/plugins/aiops/public/embeddable/embeddable_chart_component_wrapper.tsx @@ -6,7 +6,7 @@ */ import { type Observable } from 'rxjs'; -import React, { FC, useCallback, useEffect, useMemo } from 'react'; +import React, { FC, useEffect, useMemo } from 'react'; import { useTimefilter } from '@kbn/ml-date-picker'; import { css } from '@emotion/react'; import useObservable from 'react-use/lib/useObservable'; @@ -21,11 +21,7 @@ import type { } from './embeddable_change_point_chart'; import { EmbeddableChangePointChartProps } from './embeddable_change_point_chart_component'; import { FilterQueryContextProvider, useFilerQueryUpdates } from '../hooks/use_filters_query'; -import { - DataSourceContextProvider, - type DataSourceContextProviderProps, - useDataSource, -} from '../hooks/use_data_source'; +import { DataSourceContextProvider, useDataSource } from '../hooks/use_data_source'; import { useAiopsAppContext } from '../hooks/use_aiops_app_context'; import { useTimeBuckets } from '../hooks/use_time_buckets'; import { createMergedEsQuery } from '../application/utils/search_utils'; @@ -59,16 +55,9 @@ export const EmbeddableInputTracker: FC = ({ }) => { const input = useObservable(input$, initialInput); - const onChange = useCallback>( - ({ dataViews }) => { - onOutputChange({ indexPatterns: dataViews }); - }, - [onOutputChange] - ); - return ( - + 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 8a94b60aa351b..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,1215 +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` + ); + }); - describe('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', @@ -1987,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', @@ -2019,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', @@ -2188,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', @@ -2292,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/authorization/alerting_authorization.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts index 83f90b68a99b1..d6fb8d415e57f 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.test.ts @@ -750,6 +750,8 @@ describe('AlertingAuthorization', () => { name: 'myOtherAppAlertType', producer: 'alerts', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }; const myAppAlertType: RegistryRuleType = { actionGroups: [], @@ -762,6 +764,8 @@ describe('AlertingAuthorization', () => { name: 'myAppAlertType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }; const mySecondAppAlertType: RegistryRuleType = { actionGroups: [], @@ -774,6 +778,8 @@ describe('AlertingAuthorization', () => { name: 'mySecondAppAlertType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }; const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType, mySecondAppAlertType]); test('omits filter when there is no authorization api', async () => { @@ -1145,6 +1151,8 @@ describe('AlertingAuthorization', () => { name: 'myOtherAppAlertType', producer: 'myOtherApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }; const myAppAlertType: RegistryRuleType = { actionGroups: [], @@ -1157,6 +1165,8 @@ describe('AlertingAuthorization', () => { name: 'myAppAlertType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }; const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType]); beforeEach(() => { @@ -1188,75 +1198,79 @@ describe('AlertingAuthorization', () => { AlertingAuthorizationEntity.Rule ) ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "alerts": Object { - "all": true, - "read": true, - }, - "myApp": Object { - "all": true, - "read": true, - }, - "myAppWithSubFeature": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": true, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "alerts": Object { - "all": true, - "read": true, - }, - "myApp": Object { - "all": true, - "read": true, - }, - "myAppWithSubFeature": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": true, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, - } - `); + Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "myApp": Object { + "all": true, + "read": true, + }, + "myAppWithSubFeature": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": true, + "read": true, + }, + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myAppAlertType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "myApp": Object { + "all": true, + "read": true, + }, + "myAppWithSubFeature": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": true, + "read": true, + }, + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myOtherAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myOtherAppAlertType", + "producer": "myOtherApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + } + `); }); test('augments a list of types with consumers under which the operation is authorized', async () => { @@ -1312,59 +1326,63 @@ describe('AlertingAuthorization', () => { AlertingAuthorizationEntity.Rule ) ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "alerts": Object { - "all": true, - "read": true, - }, - "myApp": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": true, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, - } - `); + Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": true, + "read": true, + }, + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myOtherAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myOtherAppAlertType", + "producer": "myOtherApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "myApp": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": true, + "read": true, + }, + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myAppAlertType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + } + `); }); test('authorizes user under the `alerts` consumer when they are authorized by the producer', async () => { @@ -1407,34 +1425,36 @@ describe('AlertingAuthorization', () => { AlertingAuthorizationEntity.Alert ) ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "alerts": Object { - "all": true, - "read": true, - }, - "myApp": Object { - "all": true, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, - } - `); + Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "myApp": Object { + "all": true, + "read": true, + }, + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myAppAlertType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + } + `); }); test('augments a list of types with consumers under which multiple operations are authorized', async () => { @@ -1511,67 +1531,71 @@ describe('AlertingAuthorization', () => { AlertingAuthorizationEntity.Alert ) ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "alerts": Object { - "all": false, - "read": true, - }, - "myApp": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": false, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "alerts": Object { - "all": false, - "read": true, - }, - "myApp": Object { - "all": false, - "read": true, - }, - "myOtherApp": Object { - "all": false, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myAppAlertType", - "producer": "myApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, - } - `); + Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": false, + "read": true, + }, + "myApp": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": false, + "read": true, + }, + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myOtherAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myOtherAppAlertType", + "producer": "myOtherApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": false, + "read": true, + }, + "myApp": Object { + "all": false, + "read": true, + }, + "myOtherApp": Object { + "all": false, + "read": true, + }, + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myAppAlertType", + "producer": "myApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + } + `); }); test('omits types which have no consumers under which the operation is authorized', async () => { @@ -1627,38 +1651,40 @@ describe('AlertingAuthorization', () => { AlertingAuthorizationEntity.Alert ) ).resolves.toMatchInlineSnapshot(` - Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "alerts": Object { - "all": true, - "read": true, - }, - "myApp": Object { - "all": true, - "read": true, - }, - "myOtherApp": Object { - "all": true, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "myOtherApp", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, - } - `); + Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "alerts": Object { + "all": true, + "read": true, + }, + "myApp": Object { + "all": true, + "read": true, + }, + "myOtherApp": Object { + "all": true, + "read": true, + }, + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myOtherAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myOtherAppAlertType", + "producer": "myOtherApp", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + } + `); }); }); @@ -1674,6 +1700,8 @@ describe('AlertingAuthorization', () => { producer: 'alerts', enabledInLicense: true, isExportable: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }; const myAppAlertType: RegistryRuleType = { actionGroups: [], @@ -1686,6 +1714,8 @@ describe('AlertingAuthorization', () => { producer: 'myApp', enabledInLicense: true, isExportable: true, + hasAlertsMappings: true, + hasFieldsForAAD: true, }; const mySecondAppAlertType: RegistryRuleType = { actionGroups: [], @@ -1698,6 +1728,8 @@ describe('AlertingAuthorization', () => { producer: 'myApp', enabledInLicense: true, isExportable: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }; const setOfAlertTypes = new Set([myAppAlertType, myOtherAppAlertType, mySecondAppAlertType]); beforeEach(() => { @@ -1738,34 +1770,36 @@ describe('AlertingAuthorization', () => { AlertingAuthorizationEntity.Alert ) ).resolves.toMatchInlineSnapshot(` - Object { - "authorizedRuleTypes": Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": false, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "alerts", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, + Object { + "authorizedRuleTypes": Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": false, + "read": true, }, - "hasAllRequested": false, - "username": "some-user", - } - `); + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myOtherAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myOtherAppAlertType", + "producer": "alerts", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + }, + "hasAllRequested": false, + "username": "some-user", + } + `); }); test('it returns all authorized if user has read, get and update alert privileges', async () => { @@ -1811,34 +1845,36 @@ describe('AlertingAuthorization', () => { AlertingAuthorizationEntity.Alert ) ).resolves.toMatchInlineSnapshot(` - Object { - "authorizedRuleTypes": Set { - Object { - "actionGroups": Array [], - "actionVariables": undefined, - "authorizedConsumers": Object { - "myApp": Object { - "all": true, - "read": true, - }, - }, - "defaultActionGroupId": "default", - "enabledInLicense": true, - "id": "myOtherAppAlertType", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "myOtherAppAlertType", - "producer": "alerts", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - }, + Object { + "authorizedRuleTypes": Set { + Object { + "actionGroups": Array [], + "actionVariables": undefined, + "authorizedConsumers": Object { + "myApp": Object { + "all": true, + "read": true, }, - "hasAllRequested": false, - "username": "some-user", - } - `); + }, + "defaultActionGroupId": "default", + "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, + "id": "myOtherAppAlertType", + "isExportable": true, + "minimumLicenseRequired": "basic", + "name": "myOtherAppAlertType", + "producer": "alerts", + "recoveryActionGroup": Object { + "id": "recovered", + "name": "Recovered", + }, + }, + }, + "hasAllRequested": false, + "username": "some-user", + } + `); }); }); }); diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index 4eb901173bc89..051972b944261 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -71,8 +71,6 @@ interface HasPrivileges { type AuthorizedConsumers = Record; export interface RegistryAlertTypeWithAuth extends RegistryRuleType { authorizedConsumers: AuthorizedConsumers; - hasAlertsMappings?: boolean; - hasFieldsForAAD?: boolean; } type IsAuthorizedAtProducerLevel = boolean; @@ -371,7 +369,7 @@ export class AlertingAuthorization { const ruleTypesWithAuthorization = Array.from( this.augmentWithAuthorizedConsumers(ruleTypes, {}) ); - const ruleTypesAuthorized: Map = new Map(); + const ruleTypesAuthorized: Map = new Map(); // map from privilege to ruleType which we can refer back to when analyzing the result // of checkPrivileges const privilegeToRuleType = new Map< @@ -386,9 +384,7 @@ export class AlertingAuthorization { const ruleTypeAuth = ruleTypesWithAuthorization.find((rtwa) => rtwa.id === ruleTypeId); if (ruleTypeAuth) { if (!ruleTypesAuthorized.has(ruleTypeId)) { - const { authorizedConsumers, hasAlertsMappings, hasFieldsForAAD, ...ruleType } = - ruleTypeAuth; - ruleTypesAuthorized.set(ruleTypeId, ruleType); + ruleTypesAuthorized.set(ruleTypeId, ruleTypeAuth); } for (const operation of operations) { privilegeToRuleType.set( diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts index 5013f2fbe1552..c9e129085c3c0 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.test.ts @@ -32,6 +32,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { myApp: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { @@ -67,6 +69,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { myOtherApp: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { @@ -105,6 +109,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, { actionGroups: [], @@ -122,6 +128,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, { actionGroups: [], @@ -139,6 +147,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { @@ -177,6 +187,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, { actionGroups: [], @@ -194,6 +206,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { @@ -233,6 +247,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, { actionGroups: [], @@ -250,6 +266,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { @@ -283,6 +301,8 @@ describe('asKqlFiltersByRuleTypeAndConsumer', () => { isExportable: true, authorizedConsumers: {}, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { @@ -317,6 +337,8 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { myApp: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { @@ -379,6 +401,8 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { myOtherApp: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { @@ -449,6 +473,8 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, { actionGroups: [], @@ -466,6 +492,8 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, { actionGroups: [], @@ -483,6 +511,8 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { myAppWithSubFeature: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { @@ -646,6 +676,8 @@ describe('asEsDslFiltersByRuleTypeAndConsumer', () => { isExportable: true, authorizedConsumers: {}, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]), { 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 e14ba71c6c1bf..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,326 +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()), - } 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()), - } 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()), - } 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() { @@ -428,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/health.test.ts b/x-pack/plugins/alerting/server/routes/health.test.ts index 236d38d836bc1..b1c562ada8717 100644 --- a/x-pack/plugins/alerting/server/routes/health.test.ts +++ b/x-pack/plugins/alerting/server/routes/health.test.ts @@ -49,6 +49,8 @@ const ruleTypes = [ enabledInLicense: true, minimumScheduleInterval: '1m', defaultScheduleInterval: '10m', + hasAlertsMappings: false, + hasFieldsForAAD: false, } as RegistryAlertTypeWithAuth, ]; 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/legacy/health.test.ts b/x-pack/plugins/alerting/server/routes/legacy/health.test.ts index 19279e7dfb77a..9946f659a0744 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/health.test.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/health.test.ts @@ -53,6 +53,8 @@ const ruleTypes = [ producer: 'test', enabledInLicense: true, defaultScheduleInterval: '10m', + hasAlertsMappings: false, + hasFieldsForAAD: false, } as RegistryAlertTypeWithAuth, ]; diff --git a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts index e2c6a66cf0ab1..7262f42319c1f 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts @@ -62,6 +62,8 @@ describe('listAlertTypesRoute', () => { }, producer: 'test', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, } as RegistryAlertTypeWithAuth, ]; rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(listTypes)); @@ -85,6 +87,8 @@ describe('listAlertTypesRoute', () => { "authorizedConsumers": Object {}, "defaultActionGroupId": "default", "enabledInLicense": true, + "hasAlertsMappings": false, + "hasFieldsForAAD": false, "id": "1", "isExportable": true, "minimumLicenseRequired": "basic", @@ -137,6 +141,8 @@ describe('listAlertTypesRoute', () => { }, producer: 'alerts', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, } as RegistryAlertTypeWithAuth, ]; @@ -190,6 +196,8 @@ describe('listAlertTypesRoute', () => { }, producer: 'alerts', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, } as RegistryAlertTypeWithAuth, ]; diff --git a/x-pack/plugins/alerting/server/routes/rule_types.test.ts b/x-pack/plugins/alerting/server/routes/rule_types.test.ts index 4629293b36e10..2dab9284bb5ac 100644 --- a/x-pack/plugins/alerting/server/routes/rule_types.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule_types.test.ts @@ -61,6 +61,7 @@ describe('ruleTypesRoute', () => { defaultScheduleInterval: '10m', doesSetRecoveryContext: false, hasAlertsMappings: true, + hasFieldsForAAD: false, } as RegistryAlertTypeWithAuth, ]; const expectedResult: Array> = [ @@ -169,6 +170,8 @@ describe('ruleTypesRoute', () => { }, producer: 'alerts', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, } as RegistryAlertTypeWithAuth, ]; @@ -222,6 +225,8 @@ describe('ruleTypesRoute', () => { }, producer: 'alerts', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, } as RegistryAlertTypeWithAuth, ]; 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 57bf39ff50496..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 { @@ -67,6 +68,8 @@ export interface RegistryRuleType > { id: string; enabledInLicense: boolean; + hasFieldsForAAD: boolean; + hasAlertsMappings: boolean; } /** @@ -277,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, @@ -300,6 +305,7 @@ export class RuleTypeRegistry { indirectParamsSchema: rawRuleSchema, }, }); + if (this.alertsService && ruleType.alerts) { this.alertsService.register(ruleType.alerts as IRuleTypeAlerts); } @@ -362,26 +368,28 @@ export class RuleTypeRegistry { } public list(): Set { - return new Set( - Array.from(this.ruleTypes).map( - ([ - id, - { - name, - actionGroups, - recoveryActionGroup, - defaultActionGroupId, - actionVariables, - producer, - minimumLicenseRequired, - isExportable, - ruleTaskTimeout, - defaultScheduleInterval, - doesSetRecoveryContext, - alerts, - fieldsForAAD, - }, - ]: [string, UntypedNormalizedRuleType]) => ({ + const mapRuleTypes: Array<[string, UntypedNormalizedRuleType]> = Array.from(this.ruleTypes); + const tempRegistryRuleType = mapRuleTypes.map( + ([ + id, + { + name, + actionGroups, + recoveryActionGroup, + defaultActionGroupId, + actionVariables, + producer, + minimumLicenseRequired, + isExportable, + ruleTaskTimeout, + defaultScheduleInterval, + doesSetRecoveryContext, + alerts, + fieldsForAAD, + }, + ]) => { + // KEEP the type here to be safe if not the map is ignoring it for some reason + const ruleType: RegistryRuleType = { id, name, actionGroups, @@ -402,9 +410,11 @@ export class RuleTypeRegistry { hasFieldsForAAD: Boolean(fieldsForAAD), hasAlertsMappings: !!alerts, ...(alerts ? { alerts } : {}), - }) - ) + }; + return ruleType; + } ); + return new Set(tempRegistryRuleType); } public getAllTypes(): string[] { diff --git a/x-pack/plugins/alerting/server/rules_client/tests/aggregate.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/aggregate.test.ts index 1ae5dc7832bec..c45e74da45999 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/aggregate.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/aggregate.test.ts @@ -74,6 +74,8 @@ describe('aggregate()', () => { name: 'myType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]); beforeEach(() => { @@ -156,6 +158,8 @@ describe('aggregate()', () => { myApp: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]) ); diff --git a/x-pack/plugins/alerting/server/rules_client/tests/find.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/find.test.ts index 8475b7317af76..4b1a6fc2eba8c 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/find.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/find.test.ts @@ -82,6 +82,8 @@ describe('find()', () => { name: 'myType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]); beforeEach(() => { @@ -142,6 +144,8 @@ describe('find()', () => { myApp: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]) ); @@ -453,6 +457,8 @@ describe('find()', () => { name: 'myType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]) ); @@ -659,6 +665,8 @@ describe('find()', () => { name: 'myType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]) ); diff --git a/x-pack/plugins/alerting/server/rules_client/tests/get_tags.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/get_tags.test.ts index bf50cc5550955..1f0c4f405f2c2 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/get_tags.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/get_tags.test.ts @@ -61,6 +61,8 @@ const listedTypes = new Set([ name: 'myType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]); @@ -112,6 +114,8 @@ describe('getTags()', () => { myApp: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]) ); diff --git a/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts index 4e41d6d4d4066..9c8c78f2753f4 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/list_rule_types.test.ts @@ -67,6 +67,8 @@ describe('listRuleTypes', () => { name: 'alertingAlertType', producer: 'alerts', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }; const myAppAlertType: RegistryRuleType = { actionGroups: [], @@ -79,6 +81,8 @@ describe('listRuleTypes', () => { name: 'myAppAlertType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }; const setOfAlertTypes = new Set([myAppAlertType, alertingAlertType]); @@ -121,6 +125,8 @@ describe('listRuleTypes', () => { name: 'myType', producer: 'myApp', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, { id: 'myOtherType', @@ -132,6 +138,8 @@ describe('listRuleTypes', () => { recoveryActionGroup: RecoveredActionGroup, producer: 'alerts', enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]); beforeEach(() => { @@ -153,6 +161,8 @@ describe('listRuleTypes', () => { myApp: { read: true, all: true }, }, enabledInLicense: true, + hasAlertsMappings: false, + hasFieldsForAAD: false, }, ]); authorization.filterByRuleTypeAuthorization.mockResolvedValue(authorizedTypes); 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 ceb0c80270881..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 @@ -133,6 +133,7 @@ describe('Task Runner', () => { const inMemoryMetrics = inMemoryMetricsMock.create(); const dataViewsMock = { dataViewsServiceFactory: jest.fn().mockResolvedValue(dataViewPluginMocks.createStartContract()), + getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), } as DataViewsServerPluginStart; const alertsService = alertsServiceMock.create(); const maintenanceWindowClient = maintenanceWindowClientMock.create(); @@ -1564,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() }, }); } ); @@ -1834,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(); }); @@ -2744,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], @@ -2914,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], @@ -2931,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 73d60259b8610..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,653 +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()), - } 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/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts index 527a5d58d34d9..870cad51ed4b7 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts @@ -76,6 +76,7 @@ const alertingEventLogger = alertingEventLoggerMock.create(); const logger: ReturnType = loggingSystemMock.createLogger(); const dataViewsMock = { dataViewsServiceFactory: jest.fn().mockResolvedValue(dataViewPluginMocks.createStartContract()), + getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), } as DataViewsServerPluginStart; const alertsService = alertsServiceMock.create(); diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts index 69480563c355e..3cfa7dde78341 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts @@ -45,6 +45,7 @@ const elasticsearchService = elasticsearchServiceMock.createInternalStart(); const dataPlugin = dataPluginMock.createStartContract(); const dataViewsMock = { dataViewsServiceFactory: jest.fn().mockResolvedValue(dataViewPluginMocks.createStartContract()), + getScriptedFieldsEnabled: jest.fn().mockReturnValue(true), } as DataViewsServerPluginStart; const ruleType: UntypedNormalizedRuleType = { id: 'test', 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/apm/public/utils/non_empty_string_ref.ts b/x-pack/plugins/apm/public/utils/non_empty_string_ref.ts new file mode 100644 index 0000000000000..94cac08fa2198 --- /dev/null +++ b/x-pack/plugins/apm/public/utils/non_empty_string_ref.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const 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 dde54fa604fc7..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 @@ -57,6 +57,20 @@ import { getAllGroupByFields } from '../../../../../common/rules/get_all_groupby const ruleTypeConfig = RULE_TYPES_CONFIG[ApmRuleType.ErrorCount]; +export const errorCountActionVariables = [ + apmActionVariables.alertDetailsUrl, + apmActionVariables.environment, + apmActionVariables.errorGroupingKey, + apmActionVariables.errorGroupingName, + apmActionVariables.interval, + apmActionVariables.reason, + apmActionVariables.serviceName, + apmActionVariables.threshold, + apmActionVariables.transactionName, + apmActionVariables.triggerValue, + apmActionVariables.viewInAppUrl, +]; + export function registerErrorCountRuleType({ alerting, alertsLocator, @@ -78,19 +92,7 @@ export function registerErrorCountRuleType({ defaultActionGroupId: ruleTypeConfig.defaultActionGroupId, validate: { params: errorCountParamsSchema }, actionVariables: { - context: [ - apmActionVariables.alertDetailsUrl, - apmActionVariables.environment, - apmActionVariables.interval, - apmActionVariables.reason, - apmActionVariables.serviceName, - apmActionVariables.transactionName, - apmActionVariables.errorGroupingKey, - apmActionVariables.errorGroupingName, - apmActionVariables.threshold, - apmActionVariables.triggerValue, - apmActionVariables.viewInAppUrl, - ], + context: errorCountActionVariables, }, producer: APM_SERVER_FEATURE_ID, minimumLicenseRequired: 'basic', @@ -115,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, @@ -144,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 05f1d6adf6e5b..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 @@ -71,6 +71,19 @@ import { getAllGroupByFields } from '../../../../../common/rules/get_all_groupby const ruleTypeConfig = RULE_TYPES_CONFIG[ApmRuleType.TransactionDuration]; +export const transactionDurationActionVariables = [ + apmActionVariables.alertDetailsUrl, + apmActionVariables.environment, + apmActionVariables.interval, + apmActionVariables.reason, + apmActionVariables.serviceName, + apmActionVariables.threshold, + apmActionVariables.transactionName, + apmActionVariables.transactionType, + apmActionVariables.triggerValue, + apmActionVariables.viewInAppUrl, +]; + export function registerTransactionDurationRuleType({ alerting, ruleDataClient, @@ -91,18 +104,7 @@ export function registerTransactionDurationRuleType({ defaultActionGroupId: ruleTypeConfig.defaultActionGroupId, validate: { params: transactionDurationParamsSchema }, actionVariables: { - context: [ - apmActionVariables.alertDetailsUrl, - apmActionVariables.environment, - apmActionVariables.interval, - apmActionVariables.reason, - apmActionVariables.serviceName, - apmActionVariables.transactionType, - apmActionVariables.transactionName, - apmActionVariables.threshold, - apmActionVariables.triggerValue, - apmActionVariables.viewInAppUrl, - ], + context: transactionDurationActionVariables, }, producer: APM_SERVER_FEATURE_ID, minimumLicenseRequired: 'basic', @@ -133,7 +135,7 @@ export function registerTransactionDurationRuleType({ searchAggregatedTransactions ); - const termFilterQuery = !ruleParams.kqlFilter + const termFilterQuery = !ruleParams.searchConfiguration ? [ ...termQuery(SERVICE_NAME, ruleParams.serviceName, { queryEmptyString: false, @@ -167,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 6761ca14abf86..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 @@ -66,6 +66,19 @@ import { getAllGroupByFields } from '../../../../../common/rules/get_all_groupby const ruleTypeConfig = RULE_TYPES_CONFIG[ApmRuleType.TransactionErrorRate]; +export const transactionErrorRateActionVariables = [ + apmActionVariables.alertDetailsUrl, + apmActionVariables.environment, + apmActionVariables.interval, + apmActionVariables.reason, + apmActionVariables.serviceName, + apmActionVariables.threshold, + apmActionVariables.transactionName, + apmActionVariables.transactionType, + apmActionVariables.triggerValue, + apmActionVariables.viewInAppUrl, +]; + export function registerTransactionErrorRateRuleType({ alerting, alertsLocator, @@ -88,19 +101,7 @@ export function registerTransactionErrorRateRuleType({ defaultActionGroupId: ruleTypeConfig.defaultActionGroupId, validate: { params: transactionErrorRateParamsSchema }, actionVariables: { - context: [ - apmActionVariables.alertDetailsUrl, - apmActionVariables.environment, - apmActionVariables.interval, - apmActionVariables.reason, - apmActionVariables.serviceName, - apmActionVariables.transactionName, - apmActionVariables.threshold, - apmActionVariables.transactionType, - apmActionVariables.transactionName, - apmActionVariables.triggerValue, - apmActionVariables.viewInAppUrl, - ], + context: transactionErrorRateActionVariables, }, producer: APM_SERVER_FEATURE_ID, minimumLicenseRequired: 'basic', @@ -136,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, @@ -178,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_error_document/index.ts b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_error_document/index.ts index c460acf4c3b3f..ffb1158270455 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_error_document/index.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/get_apm_error_document/index.ts @@ -54,14 +54,14 @@ export async function getApmErrorDocument({ }, }); - const error = response.hits.hits[0]?._source as APMError; + const errorDoc = response.hits.hits[0]?._source as APMError; - if (!error) { + if (!errorDoc) { return undefined; } - return pick( - error, + const formattedResponse = pick( + errorDoc, 'message', 'error', '@timestamp', @@ -71,4 +71,11 @@ export async function getApmErrorDocument({ 'span.type', 'span.subtype' ); + + const { error, ...rest } = formattedResponse; + + return { + ...rest, + errorDoc: formattedResponse.error, + }; } 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/server/routes/fleet/source_maps.ts b/x-pack/plugins/apm/server/routes/fleet/source_maps.ts index 4eb0b011cef3c..ad2bc870c7f33 100644 --- a/x-pack/plugins/apm/server/routes/fleet/source_maps.ts +++ b/x-pack/plugins/apm/server/routes/fleet/source_maps.ts @@ -19,18 +19,12 @@ import { getPackagePolicyWithSourceMap } from './get_package_policy_decorators'; const doUnzip = promisify(unzip); -interface ApmMapArtifactBody { +interface ApmSourceMapArtifactBody { serviceName: string; serviceVersion: string; bundleFilepath: string; - sourceMap: string; -} - -interface ApmSourceMapArtifactBody - extends Omit { sourceMap: SourceMap; } - export type ArtifactSourceMap = Omit & { body: ApmSourceMapArtifactBody; }; @@ -110,23 +104,6 @@ export async function createFleetSourceMapArtifact({ }); } -export async function createFleetAndroidMapArtifact({ - apmArtifactBody, - fleetPluginStart, -}: { - apmArtifactBody: ApmMapArtifactBody; - fleetPluginStart: FleetPluginStart; -}) { - const apmArtifactClient = getApmArtifactClient(fleetPluginStart); - const identifier = `${apmArtifactBody.serviceName}-${apmArtifactBody.serviceVersion}-android`; - - return apmArtifactClient.createArtifact({ - type: 'sourcemap', - identifier, - content: JSON.stringify(apmArtifactBody), - }); -} - export async function deleteFleetSourcemapArtifact({ id, fleetPluginStart, diff --git a/x-pack/plugins/apm/server/routes/source_maps/bulk_create_apm_source_maps.ts b/x-pack/plugins/apm/server/routes/source_maps/bulk_create_apm_source_maps.ts index 3aa5c9a780aa3..1495f89f0fceb 100644 --- a/x-pack/plugins/apm/server/routes/source_maps/bulk_create_apm_source_maps.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/bulk_create_apm_source_maps.ts @@ -10,7 +10,7 @@ import { Artifact } from '@kbn/fleet-plugin/server'; import { getUnzippedArtifactBody } from '../fleet/source_maps'; import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/apm_system_index_constants'; import { ApmSourceMap } from './create_apm_source_map_index_template'; -import { getEncodedSourceMapContent, getSourceMapId } from './sourcemap_utils'; +import { getEncodedContent, getSourceMapId } from './sourcemap_utils'; export async function bulkCreateApmSourceMaps({ artifacts, @@ -24,7 +24,7 @@ export async function bulkCreateApmSourceMaps({ const { serviceName, serviceVersion, bundleFilepath, sourceMap } = await getUnzippedArtifactBody(artifact.body); - const { contentEncoded, contentHash } = await getEncodedSourceMapContent( + const { contentEncoded, contentHash } = await getEncodedContent( sourceMap ); diff --git a/x-pack/plugins/apm/server/routes/source_maps/create_apm_source_map.ts b/x-pack/plugins/apm/server/routes/source_maps/create_apm_source_map.ts index bda2601080434..95614778024fa 100644 --- a/x-pack/plugins/apm/server/routes/source_maps/create_apm_source_map.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/create_apm_source_map.ts @@ -10,11 +10,7 @@ import { Logger } from '@kbn/core/server'; import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/apm_system_index_constants'; import { ApmSourceMap } from './create_apm_source_map_index_template'; import { SourceMap } from './route'; -import { - getEncodedSourceMapContent, - getEncodedContent, - getSourceMapId, -} from './sourcemap_utils'; +import { getEncodedContent, getSourceMapId } from './sourcemap_utils'; export async function createApmSourceMap({ internalESClient, @@ -35,75 +31,9 @@ export async function createApmSourceMap({ serviceName: string; serviceVersion: string; }) { - const { contentEncoded, contentHash } = await getEncodedSourceMapContent( + const { contentEncoded, contentHash } = await getEncodedContent( sourceMapContent ); - return await doCreateApmMap({ - internalESClient, - logger, - fleetId, - created, - bundleFilepath, - serviceName, - serviceVersion, - contentEncoded, - contentHash, - }); -} - -export async function createApmAndroidMap({ - internalESClient, - logger, - fleetId, - created, - mapContent, - bundleFilepath, - serviceName, - serviceVersion, -}: { - internalESClient: ElasticsearchClient; - logger: Logger; - fleetId: string; - created: string; - mapContent: string; - bundleFilepath: string; - serviceName: string; - serviceVersion: string; -}) { - const { contentEncoded, contentHash } = await getEncodedContent(mapContent); - return await doCreateApmMap({ - internalESClient, - logger, - fleetId, - created, - bundleFilepath, - serviceName, - serviceVersion, - contentEncoded, - contentHash, - }); -} -async function doCreateApmMap({ - internalESClient, - logger, - fleetId, - created, - bundleFilepath, - serviceName, - serviceVersion, - contentEncoded, - contentHash, -}: { - internalESClient: ElasticsearchClient; - logger: Logger; - fleetId: string; - created: string; - bundleFilepath: string; - serviceName: string; - serviceVersion: string; - contentEncoded: string; - contentHash: string; -}) { const doc: ApmSourceMap = { fleet_id: fleetId, created, diff --git a/x-pack/plugins/apm/server/routes/source_maps/route.ts b/x-pack/plugins/apm/server/routes/source_maps/route.ts index c0cc2404af492..ae29267644668 100644 --- a/x-pack/plugins/apm/server/routes/source_maps/route.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/route.ts @@ -9,24 +9,19 @@ import { SavedObjectsClientContract } from '@kbn/core/server'; import { Artifact } from '@kbn/fleet-plugin/server'; import { jsonRt, toNumberRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; -import { either } from 'fp-ts/lib/Either'; import { ApmFeatureFlags } from '../../../common/apm_feature_flags'; import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client'; import { stringFromBufferRt } from '../../utils/string_from_buffer_rt'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { createFleetSourceMapArtifact, - createFleetAndroidMapArtifact, deleteFleetSourcemapArtifact, getCleanedBundleFilePath, listSourceMapArtifacts, ListSourceMapArtifactsResponse, updateSourceMapsOnFleetPolicies, } from '../fleet/source_maps'; -import { - createApmSourceMap, - createApmAndroidMap, -} from './create_apm_source_map'; +import { createApmSourceMap } from './create_apm_source_map'; import { deleteApmSourceMap } from './delete_apm_sourcemap'; import { runFleetSourcemapArtifactsMigration } from './schedule_source_map_migration'; @@ -46,24 +41,6 @@ export const sourceMapRt = t.intersection([ export type SourceMap = t.TypeOf; -const androidMapValidation = new t.Type( - 'ANDROID_MAP_VALIDATION', - t.string.is, - (input, context): t.Validation => - either.chain( - t.string.validate(input, context), - (str): t.Validation => { - const firstLine = str.split('\n', 1)[0]; - if (firstLine.trim() === '# compiler: R8') { - return t.success(str); - } else { - return t.failure(input, context); - } - } - ), - (a): string => a -); - function throwNotImplementedIfSourceMapNotAvailable( featureFlags: ApmFeatureFlags ): void { @@ -114,7 +91,7 @@ const uploadSourceMapRoute = createApmServerRoute({ endpoint: 'POST /api/apm/sourcemaps 2023-10-31', options: { tags: ['access:apm', 'access:apm_write'], - body: { accepts: ['multipart/form-data'], maxBytes: 100 * 1024 * 1024 }, + body: { accepts: ['multipart/form-data'] }, }, params: t.type({ body: t.type({ @@ -192,85 +169,6 @@ const uploadSourceMapRoute = createApmServerRoute({ }, }); -const uploadAndroidMapRoute = createApmServerRoute({ - endpoint: 'POST /api/apm/androidmaps 2023-10-31', - options: { - tags: ['access:apm', 'access:apm_write'], - body: { accepts: ['multipart/form-data'], maxBytes: 100 * 1024 * 1024 }, - }, - params: t.type({ - body: t.type({ - service_name: t.string, - service_version: t.string, - map_file: t - .union([t.string, stringFromBufferRt]) - .pipe(androidMapValidation), - }), - }), - handler: async ({ - params, - plugins, - core, - logger, - featureFlags, - }): Promise => { - throwNotImplementedIfSourceMapNotAvailable(featureFlags); - - const { - service_name: serviceName, - service_version: serviceVersion, - map_file: sourceMapContent, - } = params.body; - const bundleFilepath = 'android'; - const fleetPluginStart = await plugins.fleet?.start(); - const coreStart = await core.start(); - const internalESClient = coreStart.elasticsearch.client.asInternalUser; - const savedObjectsClient = await getInternalSavedObjectsClient(coreStart); - try { - if (fleetPluginStart) { - // create source map as fleet artifact - const artifact = await createFleetAndroidMapArtifact({ - fleetPluginStart, - apmArtifactBody: { - serviceName, - serviceVersion, - bundleFilepath, - sourceMap: sourceMapContent, - }, - }); - - // sync source map to APM managed index - await createApmAndroidMap({ - internalESClient, - logger, - fleetId: artifact.id, - created: artifact.created, - mapContent: sourceMapContent, - bundleFilepath, - serviceName, - serviceVersion, - }); - - // sync source map to fleet policy - await updateSourceMapsOnFleetPolicies({ - coreStart, - fleetPluginStart, - savedObjectsClient: - savedObjectsClient as unknown as SavedObjectsClientContract, - internalESClient, - }); - - return artifact; - } - } catch (e) { - throw Boom.internal( - 'Something went wrong while creating a new android map', - e - ); - } - }, -}); - const deleteSourceMapRoute = createApmServerRoute({ endpoint: 'DELETE /api/apm/sourcemaps/{id} 2023-10-31', options: { tags: ['access:apm', 'access:apm_write'] }, @@ -332,6 +230,5 @@ export const sourceMapsRouteRepository = { ...listSourceMapRoute, ...uploadSourceMapRoute, ...deleteSourceMapRoute, - ...uploadAndroidMapRoute, ...migrateFleetArtifactsSourceMapRoute, }; diff --git a/x-pack/plugins/apm/server/routes/source_maps/sourcemap_utils.ts b/x-pack/plugins/apm/server/routes/source_maps/sourcemap_utils.ts index 408d1b98f9c5a..20ff2fa4bd41c 100644 --- a/x-pack/plugins/apm/server/routes/source_maps/sourcemap_utils.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/sourcemap_utils.ts @@ -16,11 +16,8 @@ function asSha256Encoded(content: BinaryLike): string { return createHash('sha256').update(content).digest('hex'); } -export async function getEncodedSourceMapContent(sourceMapContent: SourceMap) { - return getEncodedContent(JSON.stringify(sourceMapContent)); -} -export async function getEncodedContent(textContent: string) { - const contentBuffer = Buffer.from(textContent); +export async function getEncodedContent(sourceMapContent: SourceMap) { + const contentBuffer = Buffer.from(JSON.stringify(sourceMapContent)); const contentZipped = await deflateAsync(contentBuffer); const contentEncoded = contentZipped.toString('base64'); const contentHash = asSha256Encoded(contentZipped); 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/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx index a6d2b7b42d38b..915676b8f6b5c 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx @@ -19,6 +19,7 @@ const testFactories: EmbeddableFactoryDefinition[] = [ getIconType: () => '', getDescription: () => 'Description for anomaly swimlane', isEditable: () => Promise.resolve(true), + latestVersion: '1.0.0', create: () => Promise.resolve({ id: 'swimlane_embeddable' } as IEmbeddable), grouping: [ { @@ -35,6 +36,7 @@ const testFactories: EmbeddableFactoryDefinition[] = [ getDescription: () => 'Description for anomaly chart', isEditable: () => Promise.resolve(true), create: () => Promise.resolve({ id: 'anomaly_chart_embeddable' } as IEmbeddable), + latestVersion: '1.0.0', grouping: [ { id: 'ml', @@ -48,6 +50,7 @@ const testFactories: EmbeddableFactoryDefinition[] = [ getDisplayName: () => 'Log stream', getIconType: () => '', getDescription: () => 'Description for log stream', + latestVersion: '1.0.0', isEditable: () => Promise.resolve(true), create: () => Promise.resolve({ id: 'anomaly_chart_embeddable' } as IEmbeddable), }, diff --git a/x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/event_handlers.ts b/x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/event_handlers.ts index bb06444c0c8f6..ca187a8381d29 100644 --- a/x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/event_handlers.ts +++ b/x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/event_handlers.ts @@ -61,7 +61,8 @@ const setupHandler = (commit: CommitFn, canvasOrigin: CanvasOriginFn, zoomScale? // only commits the cursor position if there's a way to latch onto x/y calculation (canvasOrigin is knowable) // or if left button is being held down (i.e. an element is being dragged) - if (buttons === 1 || canvasOrigin) { + // + if (buttons === 1 || canvasOrigin !== undefined) { commit('cursorPosition', { x, y, altKey, metaKey, shiftKey, ctrlKey }); } else { // clears cursorPosition 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/public/components/all_cases/all_cases_list.test.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx index 180a8828c88b1..10b55c0e979b3 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx @@ -191,7 +191,10 @@ describe('AllCasesListGeneric', () => { expect( screen.getAllByTestId('case-table-column-createdAt')[0].querySelector('.euiToolTipAnchor') ).toHaveTextContent(removeMsFromDate(useGetCasesMockState.data.cases[0].createdAt)); - expect(screen.getByTestId('case-table-case-count')).toHaveTextContent('Showing 10 cases'); + expect(screen.getByTestId('case-table-case-count')).toHaveTextContent( + `Showing 10 of ${useGetCasesMockState.data.total} cases` + ); + expect(screen.queryByTestId('all-cases-maximum-limit-warning')).not.toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/cases/public/components/all_cases/table.tsx b/x-pack/plugins/cases/public/components/all_cases/table.tsx index dc5e7042ec9f7..ae60e942dc75a 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table.tsx @@ -79,6 +79,7 @@ export const CasesTable: FunctionComponent = ({ ) : ( <> defaultMessage: 'Selected {totalRules} {totalRules, plural, =1 {case} other {cases}}', }); -export const SHOWING_CASES = (totalRules: number) => +export const SHOWING_CASES = (totalRules: number, pageSize: number) => i18n.translate('xpack.cases.caseTable.showingCasesTitle', { - values: { totalRules }, - defaultMessage: 'Showing {totalRules} {totalRules, plural, =1 {case} other {cases}}', + values: { totalRules, pageSize }, + defaultMessage: + 'Showing {pageSize} of {totalRules} {totalRules, plural, =1 {case} other {cases}}', + }); + +export const MAX_CASES = (maxCases: number) => + i18n.translate('xpack.cases.caseTable.maxCases', { + values: { maxCases }, + defaultMessage: + 'The results were capped at {maxCases} to maintain performance. Try limiting your search to reduce the results.', }); +export const DISMISS = i18n.translate('xpack.cases.caseTable.dismiss', { + defaultMessage: 'Dismiss', +}); + +export const NOT_SHOW_AGAIN = i18n.translate('xpack.cases.caseTable.notShowAgain', { + defaultMessage: 'Do not show again', +}); + export const UNIT = (totalCount: number) => i18n.translate('xpack.cases.caseTable.unit', { values: { totalCount }, diff --git a/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx b/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx index 2fddd22a9083c..4d740c2fb9552 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx @@ -5,10 +5,11 @@ * 2.0. */ -import { act, waitFor } from '@testing-library/react'; +import { act, waitFor, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import type { AppMockRenderer } from '../../common/mock'; +import { MAX_DOCS_PER_PAGE } from '../../../common/constants'; import { noCasesPermissions, onlyDeleteCasesPermission, @@ -22,11 +23,17 @@ import { CasesTableUtilityBar } from './utility_bar'; describe('Severity form field', () => { let appMockRender: AppMockRenderer; const deselectCases = jest.fn(); + const localStorageKey = 'cases.testAppId.utilityBar.hideMaxLimitWarning'; const props = { totalCases: 5, selectedCases: [basicCase], deselectCases, + pagination: { + pageIndex: 1, + pageSize: 10, + totalItemCount: 5, + }, }; beforeEach(() => { @@ -34,52 +41,89 @@ describe('Severity form field', () => { }); it('renders', async () => { - const result = appMockRender.render(); - expect(result.getByText('Showing 5 cases')).toBeInTheDocument(); - expect(result.getByText('Selected 1 case')).toBeInTheDocument(); - expect(result.getByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument(); - expect(result.getByTestId('all-cases-refresh-link-icon')).toBeInTheDocument(); + appMockRender.render(); + expect(screen.getByText('Showing 5 of 5 cases')).toBeInTheDocument(); + expect(screen.getByText('Selected 1 case')).toBeInTheDocument(); + expect(screen.getByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument(); + expect(screen.getByTestId('all-cases-refresh-link-icon')).toBeInTheDocument(); + expect(screen.queryByTestId('all-cases-maximum-limit-warning')).not.toBeInTheDocument(); + }); + + it('renders showing cases correctly', async () => { + const updatedProps = { + ...props, + totalCases: 20, + pagination: { + ...props.pagination, + totalItemCount: 20, + }, + }; + appMockRender.render(); + expect(screen.getByText('Showing 10 of 20 cases')).toBeInTheDocument(); + expect(screen.getByText('Selected 1 case')).toBeInTheDocument(); + }); + + it('renders showing cases correctly for second page', async () => { + const updatedProps = { + ...props, + totalCases: 20, + pagination: { + ...props.pagination, + pageIndex: 2, + totalItemCount: 20, + }, + }; + appMockRender.render(); + expect(screen.getByText('Showing 10 of 20 cases')).toBeInTheDocument(); + expect(screen.getByText('Selected 1 case')).toBeInTheDocument(); + }); + + it('renders showing cases correctly when no cases available', async () => { + const updatedProps = { + totalCases: 0, + selectedCases: [], + deselectCases, + pagination: { + pageSize: 10, + pageIndex: 1, + totalItemCount: 0, + }, + }; + appMockRender.render(); + expect(screen.getByText('Showing 0 of 0 cases')).toBeInTheDocument(); }); it('opens the bulk actions correctly', async () => { - const result = appMockRender.render(); + appMockRender.render(); - act(() => { - userEvent.click(result.getByTestId('case-table-bulk-actions-link-icon')); - }); + userEvent.click(screen.getByTestId('case-table-bulk-actions-link-icon')); await waitFor(() => { - expect(result.getByTestId('case-table-bulk-actions-context-menu')); + expect(screen.getByTestId('case-table-bulk-actions-context-menu')); }); }); it('closes the bulk actions correctly', async () => { - const result = appMockRender.render(); + appMockRender.render(); - act(() => { - userEvent.click(result.getByTestId('case-table-bulk-actions-link-icon')); - }); + userEvent.click(screen.getByTestId('case-table-bulk-actions-link-icon')); await waitFor(() => { - expect(result.getByTestId('case-table-bulk-actions-context-menu')); + expect(screen.getByTestId('case-table-bulk-actions-context-menu')); }); - act(() => { - userEvent.click(result.getByTestId('case-table-bulk-actions-link-icon')); - }); + userEvent.click(screen.getByTestId('case-table-bulk-actions-link-icon')); await waitFor(() => { - expect(result.queryByTestId('case-table-bulk-actions-context-menu')).toBeFalsy(); + expect(screen.queryByTestId('case-table-bulk-actions-context-menu')).toBeFalsy(); }); }); it('refresh correctly', async () => { - const result = appMockRender.render(); + appMockRender.render(); const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - act(() => { - userEvent.click(result.getByTestId('all-cases-refresh-link-icon')); - }); + userEvent.click(screen.getByTestId('all-cases-refresh-link-icon')); await waitFor(() => { expect(deselectCases).toHaveBeenCalled(); @@ -91,29 +135,198 @@ describe('Severity form field', () => { it('does not show the bulk actions without update & delete permissions', async () => { appMockRender = createAppMockRenderer({ permissions: noCasesPermissions() }); - const result = appMockRender.render(); + appMockRender.render(); - expect(result.queryByTestId('case-table-bulk-actions-link-icon')).toBeFalsy(); + expect(screen.queryByTestId('case-table-bulk-actions-link-icon')).toBeFalsy(); }); it('does show the bulk actions with only delete permissions', async () => { appMockRender = createAppMockRenderer({ permissions: onlyDeleteCasesPermission() }); - const result = appMockRender.render(); + appMockRender.render(); - expect(result.getByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument(); + expect(screen.getByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument(); }); it('does show the bulk actions with update permissions', async () => { appMockRender = createAppMockRenderer({ permissions: writeCasesPermissions() }); - const result = appMockRender.render(); + appMockRender.render(); - expect(result.getByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument(); + expect(screen.getByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument(); }); it('does not show the bulk actions if there are not selected cases', async () => { - const result = appMockRender.render(); + appMockRender.render(); + + expect(screen.queryByTestId('case-table-bulk-actions-link-icon')).toBeFalsy(); + expect(screen.queryByText('Showing 0 cases')).toBeFalsy(); + }); + + describe('Maximum number of cases', () => { + const newProps = { + ...props, + selectedCaseS: [], + totalCases: MAX_DOCS_PER_PAGE, + pagination: { + ...props.pagination, + totalItemCount: MAX_DOCS_PER_PAGE, + }, + }; + + const allCasesPageSize = [10, 25, 50, 100]; + + it.each(allCasesPageSize)( + `does not show warning when totalCases = ${MAX_DOCS_PER_PAGE} but pageSize(%s) * pageIndex + 1 < ${MAX_DOCS_PER_PAGE}`, + (size) => { + const newPageIndex = MAX_DOCS_PER_PAGE / size - 2; + + appMockRender.render( + + ); + + expect( + screen.getByText(`Showing ${size} of ${MAX_DOCS_PER_PAGE} cases`) + ).toBeInTheDocument(); + expect(screen.queryByTestId('all-cases-maximum-limit-warning')).not.toBeInTheDocument(); + } + ); + + it.each(allCasesPageSize)( + `shows warning when totalCases = ${MAX_DOCS_PER_PAGE} but pageSize(%s) * pageIndex + 1 = ${MAX_DOCS_PER_PAGE}`, + (size) => { + const newPageIndex = MAX_DOCS_PER_PAGE / size - 1; + + appMockRender.render( + + ); + + expect( + screen.getByText(`Showing ${size} of ${MAX_DOCS_PER_PAGE} cases`) + ).toBeInTheDocument(); + expect(screen.getByTestId('all-cases-maximum-limit-warning')).toBeInTheDocument(); + } + ); + + it.each(allCasesPageSize)( + `shows warning when totalCases = ${MAX_DOCS_PER_PAGE} but pageSize(%s) * pageIndex + 1 > ${MAX_DOCS_PER_PAGE}`, + (size) => { + const newPageIndex = MAX_DOCS_PER_PAGE / size; + + appMockRender.render( + + ); - expect(result.queryByTestId('case-table-bulk-actions-link-icon')).toBeFalsy(); - expect(result.queryByText('Showing 0 cases')).toBeFalsy(); + expect( + screen.getByText(`Showing ${size} of ${MAX_DOCS_PER_PAGE} cases`) + ).toBeInTheDocument(); + expect(screen.getByTestId('all-cases-maximum-limit-warning')).toBeInTheDocument(); + } + ); + + it('should show dismiss and do not show again buttons correctly', () => { + appMockRender.render( + + ); + + expect(screen.getByTestId('all-cases-maximum-limit-warning')).toBeInTheDocument(); + expect(screen.getByTestId('dismiss-warning')).toBeInTheDocument(); + + expect(screen.getByTestId('do-not-show-warning')).toBeInTheDocument(); + }); + + it('should dismiss warning correctly', () => { + appMockRender.render( + + ); + + expect(screen.getByTestId('all-cases-maximum-limit-warning')).toBeInTheDocument(); + expect(screen.getByTestId('dismiss-warning')).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('dismiss-warning')); + + expect(screen.queryByTestId('all-cases-maximum-limit-warning')).not.toBeInTheDocument(); + }); + + describe('do not show button', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.clearAllTimers(); + }); + + afterAll(() => { + jest.useRealTimers(); + sessionStorage.removeItem(localStorageKey); + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should set storage key correctly', () => { + appMockRender.render( + + ); + + expect(screen.getByTestId('all-cases-maximum-limit-warning')).toBeInTheDocument(); + expect(screen.getByTestId('do-not-show-warning')).toBeInTheDocument(); + + expect(localStorage.getItem(localStorageKey)).toBe(null); + }); + + it('should hide warning correctly when do not show button clicked', () => { + appMockRender.render( + + ); + + expect(screen.getByTestId('all-cases-maximum-limit-warning')).toBeInTheDocument(); + expect(screen.getByTestId('do-not-show-warning')).toBeInTheDocument(); + + userEvent.click(screen.getByTestId('do-not-show-warning')); + + act(() => { + jest.advanceTimersByTime(1000); + }); + + expect(screen.queryByTestId('all-cases-maximum-limit-warning')).not.toBeInTheDocument(); + expect(localStorage.getItem(localStorageKey)).toBe('true'); + }); + }); }); }); diff --git a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx index 4afc8e7e681a0..2c2aebdb30bb2 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx @@ -6,7 +6,10 @@ */ import type { FunctionComponent } from 'react'; +import { css } from '@emotion/react'; +import useLocalStorage from 'react-use/lib/useLocalStorage'; import React, { useCallback, useState } from 'react'; +import type { Pagination } from '@elastic/eui'; import { EuiButtonEmpty, EuiContextMenu, @@ -15,9 +18,12 @@ import { EuiPopover, EuiText, useEuiTheme, + EuiCallOut, + EuiSpacer, } from '@elastic/eui'; import * as i18n from './translations'; import type { CasesUI } from '../../../common/ui/types'; +import { MAX_DOCS_PER_PAGE } from '../../../common/constants'; import { useRefreshCases } from './use_on_refresh_cases'; import { useBulkActions } from './use_bulk_actions'; import { useCasesContext } from '../cases_context/use_cases_context'; @@ -27,16 +33,27 @@ interface Props { totalCases: number; selectedCases: CasesUI; deselectCases: () => void; + pagination: Pagination; } export const CasesTableUtilityBar: FunctionComponent = React.memo( - ({ isSelectorView, totalCases, selectedCases, deselectCases }) => { + ({ isSelectorView, totalCases, selectedCases, deselectCases, pagination }) => { const { euiTheme } = useEuiTheme(); + const refreshCases = useRefreshCases(); + const { permissions, appId } = useCasesContext(); + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const [isMessageDismissed, setIsMessageDismissed] = useState(false); + const localStorageKey = `cases.${appId}.utilityBar.hideMaxLimitWarning`; + const [localStorageWarning, setLocalStorageWarning] = useLocalStorage(localStorageKey); + const togglePopover = useCallback(() => setIsPopoverOpen(!isPopoverOpen), [isPopoverOpen]); const closePopover = useCallback(() => setIsPopoverOpen(false), []); - const refreshCases = useRefreshCases(); - const { permissions } = useCasesContext(); + + const toggleWarning = useCallback( + () => setIsMessageDismissed(!isMessageDismissed), + [isMessageDismissed] + ); const onRefresh = useCallback(() => { deselectCases(); @@ -49,6 +66,10 @@ export const CasesTableUtilityBar: FunctionComponent = React.memo( onActionSuccess: onRefresh, }); + const handleNotShowAgain = () => { + setLocalStorageWarning(true); + }; + /** * At least update or delete permissions needed to show bulk actions. * Granular permission check for each action is performed @@ -56,6 +77,52 @@ export const CasesTableUtilityBar: FunctionComponent = React.memo( */ const showBulkActions = (permissions.update || permissions.delete) && selectedCases.length > 0; + const visibleCases = + pagination?.pageSize && totalCases > pagination.pageSize ? pagination.pageSize : totalCases; + + const hasReachedMaxCases = + pagination.pageSize && + totalCases >= MAX_DOCS_PER_PAGE && + pagination.pageSize * (pagination.pageIndex + 1) >= MAX_DOCS_PER_PAGE; + + const isDoNotShowAgainSelected = localStorageWarning && localStorageWarning === true; + + const renderMaxLimitWarning = (): React.ReactNode => ( + + + + {i18n.MAX_CASES(MAX_DOCS_PER_PAGE)} + + + + + {i18n.DISMISS} + + + + + {i18n.NOT_SHOW_AGAIN} + + + + ); + return ( <> = React.memo( }} > - {i18n.SHOWING_CASES(totalCases)} + {i18n.SHOWING_CASES(totalCases, visibleCases)} @@ -136,6 +203,22 @@ export const CasesTableUtilityBar: FunctionComponent = React.memo( {modals} {flyouts} + {hasReachedMaxCases && !isMessageDismissed && !isDoNotShowAgainSelected && ( + <> + + + + + + + + + )} ); } diff --git a/x-pack/plugins/cases/public/components/create/form.test.tsx b/x-pack/plugins/cases/public/components/create/form.test.tsx index 50ea8e402ce83..20502756db502 100644 --- a/x-pack/plugins/cases/public/components/create/form.test.tsx +++ b/x-pack/plugins/cases/public/components/create/form.test.tsx @@ -69,6 +69,7 @@ describe('CreateCaseForm', () => { globalForm = form; return ( + // @ts-expect-error ts upgrade v4.7.4
    {children}
    diff --git a/x-pack/plugins/cases/public/components/markdown_editor/editable_markdown_renderer.test.tsx b/x-pack/plugins/cases/public/components/markdown_editor/editable_markdown_renderer.test.tsx index af114e8ec473e..636fa61b8d6f0 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/editable_markdown_renderer.test.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/editable_markdown_renderer.test.tsx @@ -72,6 +72,7 @@ describe('EditableMarkdown', () => { }); return ( + // @ts-expect-error ts upgrade v4.7.4
    {children}
    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_defend/kibana.jsonc b/x-pack/plugins/cloud_defend/kibana.jsonc index fc9cf6eb924cd..d7854913945ff 100644 --- a/x-pack/plugins/cloud_defend/kibana.jsonc +++ b/x-pack/plugins/cloud_defend/kibana.jsonc @@ -1,7 +1,7 @@ { "type": "plugin", "id": "@kbn/cloud-defend-plugin", - "owner": "@elastic/sec-cloudnative-integrations", + "owner": "@elastic/kibana-cloud-security-posture", "description": "Defend for containers (D4C)", "plugin": { "id": "cloudDefend", diff --git a/x-pack/plugins/cloud_defend/server/routes/status/status.test.ts b/x-pack/plugins/cloud_defend/server/routes/status/status.test.ts index 4c03d28baff09..57de16e86f7cf 100644 --- a/x-pack/plugins/cloud_defend/server/routes/status/status.test.ts +++ b/x-pack/plugins/cloud_defend/server/routes/status/status.test.ts @@ -53,7 +53,7 @@ const mockLatestCloudDefendPackageInfo: RegistryPackage = { download: '/epr/cloud_defend/cloud_defend-1.0.0.zip', path: '/package/cloud_defend/1.0.0', policy_templates: [], - owner: { github: 'elastic/sec-cloudnative-integrations' }, + owner: { github: 'elastic/kibana-cloud-security-posture' }, categories: ['containers', 'kubernetes'], }; 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/schemas/csp_vulnerability_finding.ts b/x-pack/plugins/cloud_security_posture/common/schemas/csp_vulnerability_finding.ts index 122e95f3b7c33..f650b115316df 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_vulnerability_finding.ts +++ b/x-pack/plugins/cloud_security_posture/common/schemas/csp_vulnerability_finding.ts @@ -70,13 +70,18 @@ export interface CspVulnerabilityFinding { commit_sha: string; commit_time: string; }; + package: { + version: string; + name: string; + fixed_version?: string; + }; } export interface Vulnerability { published_date: string; - score: { - version: string; - base: number; + score?: { + version?: string; + base?: number; }; cwe: string[]; id: string; @@ -99,11 +104,6 @@ export interface Vulnerability { scanner: { vendor: string; }; - package: { - version: string; - name: string; - fixed_version?: string; - }; } export interface VectorScoreBase { 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 bcbe41cdc96bc..0000000000000 --- a/x-pack/plugins/cloud_security_posture/common/utils/get_safe_vulnerabilities_query_filter.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; - -export const getSafeVulnerabilitiesQueryFilter = (query?: QueryDslQueryContainer) => ({ - ...query, - bool: { - ...query?.bool, - filter: [ - ...((query?.bool?.filter as []) || []), - { exists: { field: 'vulnerability.score.base' } }, - { exists: { field: 'vulnerability.score.version' } }, - { 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/_mocks_/vulnerability.mock.ts b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/_mocks_/vulnerability.mock.ts index 7f8e22eafb1b6..20c7e4ebc48b9 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/_mocks_/vulnerability.mock.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/_mocks_/vulnerability.mock.ts @@ -27,6 +27,7 @@ export const mockVulnerabilityHit: CspVulnerabilityFinding = { machine: { type: 'c6g.medium' }, region: 'eu-west-1', }, + package: { fixed_version: '0.4.0', version: 'v0.2.0', name: 'golang.org/x/net' }, vulnerability: { published_date: '2022-08-10T00:00:00.000Z', data_source: { @@ -34,7 +35,6 @@ export const mockVulnerabilityHit: CspVulnerabilityFinding = { Name: 'The Go Vulnerability Database', URL: 'https://github.com/golang/vulndb', }, - package: { fixed_version: '0.4.0', version: 'v0.2.0', name: 'golang.org/x/net' }, enumeration: 'CVE', description: 'An attacker can cause excessive memory growth in a Go server accepting HTTP/2 requests. HTTP/2 server connections contain a cache of HTTP header keys sent by the client. While the total number of entries in this cache is capped, an attacker sending very large keys can cause the server to allocate approximately 64 MiB per open connection.', 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/utils/get_vulnerabilities_grid_cell_actions.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/utils/get_vulnerabilities_grid_cell_actions.test.tsx new file mode 100644 index 0000000000000..1f84f294d8be1 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/utils/get_vulnerabilities_grid_cell_actions.test.tsx @@ -0,0 +1,189 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getRowValueByColumnId } from './get_vulnerabilities_grid_cell_actions'; +import { vulnerabilitiesColumns } from '../vulnerabilities_table_columns'; +import { vulnerabilitiesByResourceColumns } from '../vulnerabilities_by_resource/vulnerabilities_by_resource_table_columns'; +import { CspVulnerabilityFinding } from '../../../../common/schemas'; + +describe('getRowValueByColumnId', () => { + it('should return vulnerability id', () => { + const vulnerabilityRow = { + vulnerability: { + id: 'CVE-2017-1000117', + }, + }; + const columns = vulnerabilitiesColumns; + const columnId = columns.vulnerability; + + expect( + getRowValueByColumnId(vulnerabilityRow as Partial, columns, columnId) + ).toEqual('CVE-2017-1000117'); + }); + + it('should return base as a vulnerability score', () => { + const vulnerabilityRow = { + vulnerability: { + score: { + base: 5, + version: 'v1', + }, + }, + }; + const columns = vulnerabilitiesColumns; + const columnId = columns.cvss; + + expect( + getRowValueByColumnId(vulnerabilityRow as Partial, columns, columnId) + ).toEqual(5); + }); + + it('should return undefined when no base score is available', () => { + const vulnerabilityRow = { + vulnerability: {}, + }; + const columns = vulnerabilitiesColumns; + const columnId = columns.cvss; + + expect( + getRowValueByColumnId(vulnerabilityRow as Partial, columns, columnId) + ).toEqual(undefined); + + const vulnerabilityRow2 = { + vulnerability: { + score: { + version: 'v1', + }, + }, + }; + + expect( + getRowValueByColumnId( + vulnerabilityRow2 as Partial, + columns, + columnId + ) + ).toEqual(undefined); + }); + + it('should return resource id', () => { + const vulnerabilityRow = { + resource: { + id: 'i-1234567890abcdef0', + }, + }; + const columns = vulnerabilitiesByResourceColumns; + const columnId = columns.resourceId; + + expect( + getRowValueByColumnId(vulnerabilityRow as Partial, columns, columnId) + ).toEqual('i-1234567890abcdef0'); + }); + + it('should return resource name', () => { + const vulnerabilityRow = { + resource: { + name: 'test', + }, + }; + const columns1 = vulnerabilitiesByResourceColumns; + const columns2 = vulnerabilitiesColumns; + const columnId1 = columns1.resourceName; + const columnId2 = columns2.resourceName; + + expect( + getRowValueByColumnId( + vulnerabilityRow as Partial, + columns1, + columnId1 + ) + ).toEqual('test'); + expect( + getRowValueByColumnId( + vulnerabilityRow as Partial, + columns2, + columnId2 + ) + ).toEqual('test'); + }); + + it('should return vulnerability severity', () => { + const vulnerabilityRow = { + vulnerability: { + severity: 'high', + }, + }; + const columns = vulnerabilitiesColumns; + const columnId = columns.severity; + + expect( + getRowValueByColumnId(vulnerabilityRow as Partial, columns, columnId) + ).toEqual('high'); + }); + + it('should return package fields', () => { + const vulnerabilityRow = { + package: { + name: 'test', + version: '1.0.0', + fixed_version: '1.0.1', + }, + }; + const columns1 = vulnerabilitiesColumns; + const columnId1 = columns1.package; + const columnId2 = columns1.version; + const columnId3 = columns1.fixedVersion; + + expect( + getRowValueByColumnId( + vulnerabilityRow as Partial, + columns1, + columnId1 + ) + ).toEqual('test'); + expect( + getRowValueByColumnId( + vulnerabilityRow as Partial, + columns1, + columnId2 + ) + ).toEqual('1.0.0'); + expect( + getRowValueByColumnId( + vulnerabilityRow as Partial, + columns1, + columnId3 + ) + ).toEqual('1.0.1'); + }); + + it('should return undefined is package is missing', () => { + const vulnerabilityRow = { + vulnerability: {}, + }; + const columns = vulnerabilitiesColumns; + const columnId = columns.package; + + expect( + getRowValueByColumnId(vulnerabilityRow as Partial, columns, columnId) + ).toEqual(undefined); + }); + + it('should return cloud region', () => { + const vulnerabilityRow = { + cloud: { + region: 'us-east-1', + }, + }; + const columns = vulnerabilitiesByResourceColumns; + const columnId = columns.region; + + expect( + getRowValueByColumnId(vulnerabilityRow as Partial, columns, columnId) + ).toEqual('us-east-1'); + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/utils/get_vulnerabilities_grid_cell_actions.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/utils/get_vulnerabilities_grid_cell_actions.tsx index b92adf84d70ab..dbde094d6f43b 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/utils/get_vulnerabilities_grid_cell_actions.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/utils/get_vulnerabilities_grid_cell_actions.tsx @@ -11,6 +11,40 @@ import { CspVulnerabilityFinding } from '../../../../common/schemas'; import { getFilters } from './get_filters'; import { FILTER_IN, FILTER_OUT } from '../translations'; +export const getRowValueByColumnId = ( + vulnerabilityRow: Partial, + columns: Record, + columnId: string +) => { + if (columnId === columns.vulnerability) { + return vulnerabilityRow.vulnerability?.id; + } + if (columnId === columns.cvss) { + return vulnerabilityRow.vulnerability?.score?.base; + } + if (columnId === columns.resourceId) { + return vulnerabilityRow.resource?.id; + } + if (columnId === columns.resourceName) { + return vulnerabilityRow.resource?.name; + } + if (columnId === columns.severity) { + return vulnerabilityRow.vulnerability?.severity; + } + if (columnId === columns.package) { + return vulnerabilityRow.package?.name; + } + if (columnId === columns.version) { + return vulnerabilityRow.package?.version; + } + if (columnId === columns.fixedVersion) { + return vulnerabilityRow.package?.fixed_version; + } + if (columnId === columns.region) { + return vulnerabilityRow.cloud?.region; + } +}; + export const getVulnerabilitiesGridCellActions = < T extends Array> >({ @@ -34,33 +68,7 @@ export const getVulnerabilitiesGridCellActions = < const vulnerabilityRow = data[rowIndex]; if (!vulnerabilityRow) return null; - if (columnId === columns.vulnerability) { - return vulnerabilityRow.vulnerability?.id; - } - if (columnId === columns.cvss) { - return vulnerabilityRow.vulnerability?.score.base; - } - if (columnId === columns.resourceId) { - return vulnerabilityRow.resource?.id; - } - if (columnId === columns.resourceName) { - return vulnerabilityRow.resource?.name; - } - if (columnId === columns.severity) { - return vulnerabilityRow.vulnerability?.severity; - } - if (columnId === columns.package) { - return vulnerabilityRow.vulnerability?.package?.name; - } - if (columnId === columns.version) { - return vulnerabilityRow.vulnerability?.package?.version; - } - if (columnId === columns.fixedVersion) { - return vulnerabilityRow.vulnerability?.package?.fixed_version; - } - if (columnId === columns.region) { - return vulnerabilityRow.cloud?.region; - } + return getRowValueByColumnId(vulnerabilityRow, columns, columnId); }; const cellActions: EuiDataGridColumnCellAction[] = [ 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 efb2b97cc6891..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 = () => { @@ -165,10 +138,8 @@ const VulnerabilitiesDataGrid = ({ (vulnerabilityRecord: VulnerabilitiesQueryData['page'][number]) => vulnerabilityRecord.vulnerability?.id === vulnerabilityRow.vulnerability?.id && vulnerabilityRecord.resource?.id === vulnerabilityRow.resource?.id && - vulnerabilityRecord.vulnerability.package.name === - vulnerabilityRow.vulnerability.package.name && - vulnerabilityRecord.vulnerability.package.version === - vulnerabilityRow.vulnerability.package.version + vulnerabilityRecord.package.name === vulnerabilityRow.package.name && + vulnerabilityRecord.package.version === vulnerabilityRow.package.version ); setUrlQuery({ vulnerabilityIndex, @@ -194,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 = ({ @@ -268,13 +241,13 @@ const VulnerabilitiesDataGrid = ({ } if (columnId === vulnerabilitiesColumns.package) { - return <>{vulnerabilityRow.vulnerability?.package?.name}; + return <>{vulnerabilityRow?.package?.name}; } if (columnId === vulnerabilitiesColumns.version) { - return <>{vulnerabilityRow.vulnerability?.package?.version}; + return <>{vulnerabilityRow?.package?.version}; } if (columnId === vulnerabilitiesColumns.fixedVersion) { - return <>{vulnerabilityRow.vulnerability?.package?.fixed_version}; + return <>{vulnerabilityRow?.package?.fixed_version}; } return null; @@ -392,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, @@ -445,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 ee67c8e073b3e..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(); @@ -124,10 +132,8 @@ const ResourceVulnerabilitiesDataGrid = ({ (vulnerabilityRecord: VulnerabilitiesQueryData['page'][number]) => vulnerabilityRecord.vulnerability?.id === vulnerabilityRow.vulnerability?.id && vulnerabilityRecord.resource?.id === vulnerabilityRow.resource?.id && - vulnerabilityRecord.vulnerability.package.name === - vulnerabilityRow.vulnerability.package.name && - vulnerabilityRecord.vulnerability.package.version === - vulnerabilityRow.vulnerability.package.version + vulnerabilityRecord.package.name === vulnerabilityRow.package.name && + vulnerabilityRecord.package.version === vulnerabilityRow.package.version ); setUrlQuery({ vulnerabilityIndex, @@ -232,13 +238,13 @@ const ResourceVulnerabilitiesDataGrid = ({ } if (columnId === vulnerabilitiesColumns.package) { - return <>{vulnerabilityRow.vulnerability?.package?.name}; + return <>{vulnerabilityRow?.package?.name}; } if (columnId === vulnerabilitiesColumns.version) { - return <>{vulnerabilityRow.vulnerability?.package?.version}; + return <>{vulnerabilityRow?.package?.version}; } if (columnId === vulnerabilitiesColumns.fixedVersion) { - return <>{vulnerabilityRow.vulnerability?.package?.fixed_version}; + return <>{vulnerabilityRow?.package?.fixed_version}; } return null; @@ -357,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, @@ -459,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/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_finding_flyout.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_finding_flyout.test.tsx index 516a25586b0ac..47acba70f97fa 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_finding_flyout.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_finding_flyout.test.tsx @@ -39,7 +39,7 @@ describe('', () => { getByText(mockVulnerabilityHit.vulnerability.description); const descriptionList = getByTestId(FINDINGS_VULNERABILITY_FLYOUT_DESCRIPTION_LIST); expect(descriptionList.textContent).toEqual( - `Resource ID:${mockVulnerabilityHit.resource?.id}Resource Name:${mockVulnerabilityHit.resource?.name}Package:${mockVulnerabilityHit.vulnerability.package.name}Version:${mockVulnerabilityHit.vulnerability.package.version}` + `Resource ID:${mockVulnerabilityHit.resource?.id}Resource Name:${mockVulnerabilityHit.resource?.name}Package:${mockVulnerabilityHit.package.name}Version:${mockVulnerabilityHit.package.version}` ); getByText(mockVulnerabilityHit.vulnerability.severity); }); @@ -59,7 +59,7 @@ describe('', () => { it('show display Vulnerability details in a Overview Tab', () => { const { getByText, getAllByText } = render( - + ); getByText(mockVulnerabilityHit.vulnerability.data_source.ID); @@ -72,7 +72,7 @@ describe('', () => { getAllByText(mockVulnerabilityHit.vulnerability?.cvss?.ghsa?.V3Vector?.toString() as string); getAllByText(mockVulnerabilityHit.vulnerability?.cvss?.ghsa?.V3Score?.toString() as string); getByText( - `${mockVulnerabilityHit.vulnerability.package.name} ${mockVulnerabilityHit.vulnerability.package.fixed_version}` + `${mockVulnerabilityHit.package.name} ${mockVulnerabilityHit.package.fixed_version}` ); }); @@ -80,9 +80,9 @@ describe('', () => { const { getByText } = render( diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_finding_flyout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_finding_flyout.tsx index ac2212c208dad..5b26029968e5a 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_finding_flyout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_finding_flyout.tsx @@ -69,14 +69,14 @@ const getFlyoutDescriptionList = ( 'xpack.csp.vulnerabilities.vulnerabilitiesFindingFlyout.flyoutDescriptionList.packageTitle', { defaultMessage: 'Package' } ), - description: vulnerabilityRecord.vulnerability.package.name, + description: vulnerabilityRecord.package.name, }, { title: i18n.translate( 'xpack.csp.vulnerabilities.vulnerabilitiesFindingFlyout.flyoutDescriptionList.versionTitle', { defaultMessage: 'Version' } ), - description: vulnerabilityRecord.vulnerability.package.version, + description: vulnerabilityRecord.package.version, }, ].filter(truthy); @@ -108,7 +108,7 @@ export const VulnerabilityFindingFlyout = ({ defaultMessage="Overview" /> ), - content: , + content: , }, { id: tableTabId, @@ -131,7 +131,7 @@ export const VulnerabilityFindingFlyout = ({ content: , }, ], - [vulnerability, vulnerabilityRecord] + [vulnerabilityRecord] ); const onSelectedTabChanged = (id: string) => setSelectedTabId(id); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx index b25b2ae982d0a..7cf91848649b0 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx @@ -19,7 +19,7 @@ import moment from 'moment'; import React from 'react'; import { euiThemeVars } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; -import { VectorScoreBase, Vulnerability } from '../../../../common/schemas'; +import { VectorScoreBase, CspVulnerabilityFinding } from '../../../../common/schemas'; import { CspFlyoutMarkdown } from '../../configurations/findings_flyout/findings_flyout'; import { NvdLogo } from '../../../assets/icons/nvd_logo_svg'; import { CVSScoreBadge } from '../../../components/vulnerability_badges'; @@ -41,7 +41,7 @@ const vendorIcons: Record = { }; interface VulnerabilityTabProps { - vulnerability: Vulnerability; + vulnerabilityRecord: CspVulnerabilityFinding; } const CVSScore = ({ vectorBaseScore, vendor }: CVSScoreProps) => { @@ -135,7 +135,8 @@ const VectorScore = ({ ); }; -const VulnerabilityOverviewTiles = ({ vulnerability }: VulnerabilityTabProps) => { +const VulnerabilityOverviewTiles = ({ vulnerabilityRecord }: VulnerabilityTabProps) => { + const { vulnerability } = vulnerabilityRecord; const tileStyle = css` padding: ${euiThemeVars.euiFontSizeM}; background: ${euiThemeVars.euiColorLightestShade}; @@ -198,7 +199,8 @@ const VulnerabilityOverviewTiles = ({ vulnerability }: VulnerabilityTabProps) => ); }; -export const VulnerabilityOverviewTab = ({ vulnerability }: VulnerabilityTabProps) => { +export const VulnerabilityOverviewTab = ({ vulnerabilityRecord }: VulnerabilityTabProps) => { + const { vulnerability } = vulnerabilityRecord; const emptyFixesMessageState = i18n.translate( 'xpack.csp.vulnerabilities.vulnerabilityOverviewTab.emptyFixesMessage', { @@ -206,8 +208,8 @@ export const VulnerabilityOverviewTab = ({ vulnerability }: VulnerabilityTabProp } ); - const fixesDisplayText = vulnerability?.package?.fixed_version - ? `${vulnerability?.package?.name} ${vulnerability?.package?.fixed_version}` + const fixesDisplayText = vulnerabilityRecord?.package?.fixed_version + ? `${vulnerabilityRecord?.package?.name} ${vulnerabilityRecord?.package?.fixed_version}` : emptyFixesMessageState; const cvssScores: JSX.Element[] = vulnerability?.cvss @@ -236,7 +238,7 @@ export const VulnerabilityOverviewTab = ({ vulnerability }: VulnerabilityTabProp return ( - + diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_table_columns.ts b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_table_columns.ts index d95fca6f51849..a3d7e2a89db15 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_table_columns.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_table_columns.ts @@ -16,9 +16,9 @@ export const vulnerabilitiesColumns = { resourceName: 'resource.name', resourceId: 'resource.id', severity: 'vulnerability.severity', - package: 'vulnerability.package.name', - version: 'vulnerability.package.version', - fixedVersion: 'vulnerability.package.fixed_version', + package: 'package.name', + version: 'package.version', + fixedVersion: 'package.fixed_version', }; const defaultColumnProps = () => ({ diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx index 4a8c3670d4483..14c3451fd2731 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx @@ -159,11 +159,19 @@ export const VulnerabilityTablePanelSection = () => { defaultMessage: 'CVSS', } ), - render: (cvss: { score: number; version: string }) => ( - onCellClick({ 'vulnerability.score.base': cvss.score })}> - - - ), + render: (cvss: PatchableVulnerabilityStat['cvss']) => { + if (!cvss.score || !cvss.version) { + return null; + } + + const esQuery = { 'vulnerability.score.base': cvss.score }; + + return ( + onCellClick(esQuery)}> + + + ); + }, }, { field: 'packageFixVersion', @@ -176,9 +184,7 @@ export const VulnerabilityTablePanelSection = () => { ), render: (packageFixVersion: string) => ( - onCellClick({ 'vulnerability.package.fixed_version': packageFixVersion }) - } + onClick={() => onCellClick({ 'package.fixed_version': packageFixVersion })} className="eui-textTruncate" color="text" > @@ -229,11 +235,19 @@ export const VulnerabilityTablePanelSection = () => { defaultMessage: 'CVSS', } ), - render: (cvss: { score: number; version: string }) => ( - onCellClick({ 'vulnerability.score.base': cvss.score })}> - - - ), + render: (cvss: VulnerabilityStat['cvss']) => { + if (!cvss.score || !cvss.version) { + return null; + } + + const esQuery = { 'vulnerability.score.base': cvss.score }; + + return ( + onCellClick(esQuery)}> + + + ); + }, }, { field: 'severity', @@ -260,7 +274,7 @@ export const VulnerabilityTablePanelSection = () => { ), render: (packageName: string) => ( onCellClick({ 'vulnerability.package.name': packageName })} + onClick={() => onCellClick({ 'package.name': packageName })} className="eui-textTruncate" color="text" > @@ -279,7 +293,7 @@ export const VulnerabilityTablePanelSection = () => { ), render: (packageVersion: string) => ( onCellClick({ 'vulnerability.package.version': packageVersion })} + onClick={() => onCellClick({ 'package.version': packageVersion })} className="eui-textTruncate" color="text" > @@ -298,9 +312,7 @@ export const VulnerabilityTablePanelSection = () => { ), render: (packageFixVersion: string) => ( - onCellClick({ 'vulnerability.package.fixed_version': packageFixVersion }) - } + onClick={() => onCellClick({ 'package.fixed_version': packageFixVersion })} className="eui-textTruncate" color="text" > 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/create_transforms/latest_vulnerabilities_transforms.ts b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_vulnerabilities_transforms.ts index 4d6515e4fb8fc..fcd3faee437a2 100644 --- a/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_vulnerabilities_transforms.ts +++ b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_vulnerabilities_transforms.ts @@ -38,12 +38,7 @@ export const latestVulnerabilitiesTransform: TransformPutTransformRequest = { }, latest: { sort: '@timestamp', - unique_key: [ - 'vulnerability.id', - 'resource.id', - 'vulnerability.package.name', - 'vulnerability.package.version', - ], + unique_key: ['vulnerability.id', 'resource.id', 'package.name', 'package.version'], }, _meta: { package: { 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 9c0e515ffeb0e..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: { @@ -104,19 +106,19 @@ const getVulnerabilitiesQuery = (query: QueryDslQueryContainer): SearchRequest = }, packageFixVersion: { terms: { - field: 'vulnerability.package.fixed_version', + field: 'package.fixed_version', size: 1, }, }, packageName: { terms: { - field: 'vulnerability.package.name', + field: 'package.name', size: 1, }, }, packageVersion: { terms: { - field: 'vulnerability.package.version', + field: 'package.version', size: 1, }, }, @@ -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/data_comparison/data_comparison_app_state.tsx b/x-pack/plugins/data_visualizer/public/application/data_comparison/data_comparison_app_state.tsx index faf36e18725cd..8844a2b9a20a9 100644 --- a/x-pack/plugins/data_visualizer/public/application/data_comparison/data_comparison_app_state.tsx +++ b/x-pack/plugins/data_visualizer/public/application/data_comparison/data_comparison_app_state.tsx @@ -15,12 +15,7 @@ import { UrlStateProvider } from '@kbn/ml-url-state'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { DatePickerContextProvider } from '@kbn/ml-date-picker'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; -import { - KibanaContextProvider, - KibanaThemeProvider, - toMountPoint, - wrapWithTheme, -} from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { DV_STORAGE_KEYS } from '../index_data_visualizer/types/storage'; import { getCoreStart, getPluginsStart } from '../../kibana_services'; @@ -77,9 +72,7 @@ export const DataComparisonDetectionAppState: FC 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/jest.config.js b/x-pack/plugins/discover_log_explorer/jest.config.js deleted file mode 100644 index 988de065d4013..0000000000000 --- a/x-pack/plugins/discover_log_explorer/jest.config.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../..', - roots: ['/x-pack/plugins/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}', - ], -}; 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/components/dataset_selector/constants.tsx b/x-pack/plugins/discover_log_explorer/public/components/dataset_selector/constants.tsx deleted file mode 100644 index a3ea4b85bbb00..0000000000000 --- a/x-pack/plugins/discover_log_explorer/public/components/dataset_selector/constants.tsx +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const POPOVER_ID = 'dataset-selector-popover'; -export const INTEGRATION_PANEL_ID = 'integrations_panel'; -export const UNMANAGED_STREAMS_PANEL_ID = 'unmanaged_streams_panel'; - -export const DATA_VIEW_POPOVER_CONTENT_WIDTH = 300; - -export const contextMenuStyles = { maxHeight: 440 }; - -export const selectDatasetLabel = i18n.translate( - 'xpack.discoverLogExplorer.datasetSelector.selectDataset', - { defaultMessage: 'Select dataset' } -); - -export const integrationsLabel = i18n.translate( - 'xpack.discoverLogExplorer.datasetSelector.integrations', - { defaultMessage: 'Integrations' } -); - -export const uncategorizedLabel = i18n.translate( - 'xpack.discoverLogExplorer.datasetSelector.uncategorized', - { defaultMessage: 'Uncategorized' } -); - -export const sortOrdersLabel = i18n.translate( - 'xpack.discoverLogExplorer.datasetSelector.sortOrders', - { defaultMessage: 'Sort directions' } -); - -export const noDatasetsLabel = i18n.translate( - 'xpack.discoverLogExplorer.datasetSelector.noDatasets', - { defaultMessage: 'No data streams found' } -); - -export const noDatasetsDescriptionLabel = i18n.translate( - 'xpack.discoverLogExplorer.datasetSelector.noDatasetsDescription', - { - defaultMessage: 'No datasets or search results found.', - } -); - -export const noIntegrationsLabel = i18n.translate( - 'xpack.discoverLogExplorer.datasetSelector.noIntegrations', - { defaultMessage: 'No integrations found' } -); - -export const noIntegrationsDescriptionLabel = i18n.translate( - 'xpack.discoverLogExplorer.datasetSelector.noIntegrationsDescription', - { - defaultMessage: 'No integrations or search results found.', - } -); - -export const errorLabel = i18n.translate('xpack.discoverLogExplorer.datasetSelector.error', { - defaultMessage: 'error', -}); - -export const noDataRetryLabel = i18n.translate( - 'xpack.discoverLogExplorer.datasetSelector.noDataRetry', - { - defaultMessage: 'Retry', - } -); - -export const sortOptions = [ - { - id: 'asc', - iconType: 'sortAscending', - label: 'Ascending', - }, - { - id: 'desc', - iconType: 'sortDescending', - label: 'Descending', - }, -]; 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/index.ts b/x-pack/plugins/discover_log_explorer/public/index.ts deleted file mode 100644 index 0c4298100c558..0000000000000 --- a/x-pack/plugins/discover_log_explorer/public/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { PluginInitializerContext } from '@kbn/core/public'; -import { DiscoverLogExplorerConfig } from '../common/plugin_config'; -import { DiscoverLogExplorerPlugin } from './plugin'; - -export function plugin(context: PluginInitializerContext) { - return new DiscoverLogExplorerPlugin(context); -} 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/state_machines/log_explorer_profile/src/notifications.ts b/x-pack/plugins/discover_log_explorer/public/state_machines/log_explorer_profile/src/notifications.ts deleted file mode 100644 index e4dc78b056814..0000000000000 --- a/x-pack/plugins/discover_log_explorer/public/state_machines/log_explorer_profile/src/notifications.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { IToasts } from '@kbn/core/public'; -import { i18n } from '@kbn/i18n'; - -export const createDatasetSelectionRestoreFailedNotifier = (toasts: IToasts) => () => - toasts.addWarning({ - title: i18n.translate( - 'xpack.discoverLogExplorer.datasetSelection.restoreDatasetSelectionFailedToastTitle', - { defaultMessage: "We couldn't restore your datasets selection." } - ), - text: i18n.translate( - 'xpack.discoverLogExplorer.datasetSelection.restoreDatasetSelectionFailedToastMessage', - { defaultMessage: 'We switched to "All log datasets" as the default selection.' } - ), - }); - -export const createCreateDataViewFailedNotifier = (toasts: IToasts) => () => - toasts.addWarning({ - title: i18n.translate( - 'xpack.discoverLogExplorer.datasetSelection.createDataViewFailedToastTitle', - { defaultMessage: "We couldn't create a data view for your selection." } - ), - text: i18n.translate( - 'xpack.discoverLogExplorer.datasetSelection.createDataViewFailedToastMessage', - { defaultMessage: 'We switched to "All log datasets" as the default selection.' } - ), - }); 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/discover_log_explorer/server/index.ts b/x-pack/plugins/discover_log_explorer/server/index.ts deleted file mode 100644 index 091fe7bb47e47..0000000000000 --- a/x-pack/plugins/discover_log_explorer/server/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { DiscoverLogExplorerServerPlugin } from './plugin'; - -export { config } from './config'; - -export const plugin = () => new DiscoverLogExplorerServerPlugin(); diff --git a/x-pack/plugins/discover_log_explorer/server/plugin.ts b/x-pack/plugins/discover_log_explorer/server/plugin.ts deleted file mode 100644 index a1e971fc2b502..0000000000000 --- a/x-pack/plugins/discover_log_explorer/server/plugin.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { Plugin } from '@kbn/core/server'; - -export class DiscoverLogExplorerServerPlugin implements Plugin { - setup() {} - - start() {} -} diff --git a/x-pack/plugins/discover_log_explorer/tsconfig.json b/x-pack/plugins/discover_log_explorer/tsconfig.json deleted file mode 100644 index 61ea70ece2d38..0000000000000 --- a/x-pack/plugins/discover_log_explorer/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types" - }, - "include": ["../../../typings/**/*", "common/**/*", "public/**/*", "server/**/*", ".storybook/**/*.tsx"], - "kbn_references": [ - "@kbn/core", - "@kbn/discover-plugin", - "@kbn/i18n", - "@kbn/i18n-react", - "@kbn/fleet-plugin", - "@kbn/io-ts-utils", - "@kbn/data-views-plugin", - "@kbn/rison", - "@kbn/controls-plugin", - "@kbn/embeddable-plugin", - "@kbn/es-query", - "@kbn/kibana-react-plugin", - "@kbn/data-plugin", - "@kbn/unified-field-list", - "@kbn/config-schema", - ], - "exclude": ["target/**/*"] -} 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/elastic_assistant/jest.config.js b/x-pack/plugins/elastic_assistant/jest.config.js new file mode 100644 index 0000000000000..7bbeb3b1c89d2 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/jest.config.js @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + collectCoverageFrom: [ + '/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/plugins/elastic_assistant/server/__mocks__/request.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts new file mode 100644 index 0000000000000..827f08683e0b8 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/request.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 { httpServerMock } from '@kbn/core/server/mocks'; + +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/encrypted_saved_objects/server/plugin.ts b/x-pack/plugins/encrypted_saved_objects/server/plugin.ts index 92a663fab64d4..7b7fed43f5181 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/plugin.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/plugin.ts @@ -95,19 +95,23 @@ export class EncryptedSavedObjectsPlugin getStartServices: core.getStartServices, }); - defineRoutes({ - router: core.http.createRouter(), - logger: this.initializerContext.logger.get('routes'), - encryptionKeyRotationService: Object.freeze( - new EncryptionKeyRotationService({ - logger: this.logger.get('key-rotation-service'), - service, - getStartServices: core.getStartServices, - security: deps.security, - }) - ), - config, - }); + // In the serverless environment, the encryption keys for saved objects is managed internally and never + // exposed to users and administrators, eliminating the need for any public Encrypted Saved Objects HTTP APIs + if (this.initializerContext.env.packageInfo.buildFlavor !== 'serverless') { + defineRoutes({ + router: core.http.createRouter(), + logger: this.initializerContext.logger.get('routes'), + encryptionKeyRotationService: Object.freeze( + new EncryptionKeyRotationService({ + logger: this.logger.get('key-rotation-service'), + service, + getStartServices: core.getStartServices, + security: deps.security, + }) + ), + config, + }); + } return { canEncrypt, diff --git a/x-pack/plugins/enterprise_search/common/connectors/connectors.ts b/x-pack/plugins/enterprise_search/common/connectors/connectors.ts index 3595ca7644770..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', { @@ -139,6 +139,17 @@ export const CONNECTOR_DEFINITIONS: ConnectorServerSideDefinition[] = [ }), serviceType: 'postgresql', }, + { + iconPath: 'salesforce.svg', + isBeta: true, + isNative: false, + isTechPreview: false, + keywords: ['salesforce', 'cloud', 'connector'], + name: i18n.translate('xpack.enterpriseSearch.content.nativeConnectors.salesforce.name', { + defaultMessage: 'Salesforce', + }), + serviceType: 'salesforce', + }, { iconPath: 'servicenow.svg', isBeta: true, 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/common/types/connectors.ts b/x-pack/plugins/enterprise_search/common/types/connectors.ts index 1ea3096f1b2e7..6354c058b222f 100644 --- a/x-pack/plugins/enterprise_search/common/types/connectors.ts +++ b/x-pack/plugins/enterprise_search/common/types/connectors.ts @@ -215,7 +215,7 @@ export interface Connector { features: ConnectorFeatures; filtering: FilteringConfig[]; id: string; - index_name: string; + index_name: string | null; is_native: boolean; language: string | null; last_access_control_sync_error: string | null; diff --git a/x-pack/plugins/enterprise_search/common/types/index.ts b/x-pack/plugins/enterprise_search/common/types/index.ts index 8519db9a3ca5b..38ac392884648 100644 --- a/x-pack/plugins/enterprise_search/common/types/index.ts +++ b/x-pack/plugins/enterprise_search/common/types/index.ts @@ -64,6 +64,9 @@ export interface Meta { export interface ClientConfigType { canDeployEntSearch: boolean; host?: string; + ui: { + enabled: boolean; + }; } export type { ElasticsearchIndexWithPrivileges } from './indices'; diff --git a/x-pack/plugins/enterprise_search/common/utils/strip_search_prefix.ts b/x-pack/plugins/enterprise_search/common/utils/strip_search_prefix.ts new file mode 100644 index 0000000000000..424ec1012d5b5 --- /dev/null +++ b/x-pack/plugins/enterprise_search/common/utils/strip_search_prefix.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 function stripSearchPrefix(input: string, replacement?: string): string { + return input?.startsWith('search-') ? `${replacement || ''}${input.substring(7)}` : input || ''; +} 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/api/crawler/types.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/types.ts index 7c9b7cfdf0541..35a5ebb232056 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/types.ts @@ -173,6 +173,7 @@ export interface CrawlScheduleFromServer { // Client export interface CrawlerCustomSchedule { + scheduleKey: string; name: string; customEntryPointUrls: string[]; customSitemapUrls: string[]; @@ -183,6 +184,8 @@ export interface CrawlerCustomSchedule { selectedSitemapUrls: string[]; interval: string; // interval has crontab syntax enabled: boolean; + entryPointUrls: string[]; + sitemapUrls: string[]; } export enum CustomCrawlType { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/utils.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/utils.ts index 4337301416191..7b3db24f29a87 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/utils.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/utils.ts @@ -248,34 +248,39 @@ export const domainConfigServerToClient = ( export const crawlerCustomSchedulingServerToClient = ( customSchedulingFromServer: CrawlerCustomSchedulesServer ): CrawlerCustomSchedule[] => - Object.entries(customSchedulingFromServer.custom_scheduling).map((scheduleMapping) => { - const { - name, - interval, - configuration_overrides: configurationOverrides, - enabled, - } = scheduleMapping[1]; - const { - max_crawl_depth: maxCrawlDepth = 2, - sitemap_discovery_disabled: notIncludeSitemapsInRobotsTxt = false, - domain_allowlist: selectedDomainUrls = [], - sitemap_urls: customSitemapUrls = [], - seed_urls: customEntryPointUrls = [], - } = configurationOverrides; - - return { - name, - interval, - enabled, - maxCrawlDepth, - includeSitemapsInRobotsTxt: !notIncludeSitemapsInRobotsTxt, - selectedDomainUrls, - selectedEntryPointUrls: [], - selectedSitemapUrls: [], - customEntryPointUrls, - customSitemapUrls, - }; - }); + Object.entries(customSchedulingFromServer.custom_scheduling).map( + ([scheduleKey, scheduleMapping]) => { + const { + name, + interval, + configuration_overrides: configurationOverrides, + enabled, + } = scheduleMapping; + const { + max_crawl_depth: maxCrawlDepth = 2, + sitemap_discovery_disabled: notIncludeSitemapsInRobotsTxt = false, + domain_allowlist: selectedDomainUrls = [], + sitemap_urls: customSitemapUrls = [], + seed_urls: customEntryPointUrls = [], + } = configurationOverrides; + + return { + scheduleKey, + name, + interval, + enabled, + maxCrawlDepth, + includeSitemapsInRobotsTxt: !notIncludeSitemapsInRobotsTxt, + selectedDomainUrls, + selectedEntryPointUrls: [], + selectedSitemapUrls: [], + customEntryPointUrls, + customSitemapUrls, + entryPointUrls: [], + sitemapUrls: [], + }; + } + ); export const crawlerCustomSchedulingClientToServer = ( crawlerCustomSchedules: CrawlerCustomSchedule[] @@ -304,8 +309,7 @@ export const crawlerCustomSchedulingClientToServer = ( const customSchedules: CrawlerCustomScheduleMappingClient = crawlerCustomSchedules.reduce( (map, schedule) => { - const scheduleNameFormatted = schedule.name.replace(/\s+/g, '_').toLowerCase(); - map.set(scheduleNameFormatted, mapToServerFormat(schedule)); + map.set(schedule.scheduleKey, mapToServerFormat(schedule)); return map; }, new Map() 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); @@ -97,20 +101,18 @@ export const APIGettingStarted = () => { language={language} setSelectedLanguage={setSelectedLanguage} isSelectedLanguage={selectedLanguage === language} - http={http} src={icons[language.id]} /> ))} { />

    - {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', + } + )}
    @@ -260,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 }} /> @@ -289,18 +271,21 @@ 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={ @@ -326,12 +311,15 @@ export const APIGettingStarted = () => { rightPanelContent={ @@ -355,12 +343,11 @@ export const APIGettingStarted = () => { rightPanelContent={ @@ -383,12 +370,15 @@ export const APIGettingStarted = () => { rightPanelContent={ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/console.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/console.ts deleted file mode 100644 index afb685441e89f..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/console.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { LanguageDefinition } from '@kbn/search-api-panels'; - -export const consoleDefinition: Partial = { - buildSearchQuery: `POST /books/_search?pretty -{ - "query": { - "query_string": { - "query": "snow" - } - } -}`, - ingestData: `POST _bulk?pretty -{ "index" : { "_index" : "books" } } -{"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} -{ "index" : { "_index" : "books" } } -{"name": "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585} -{ "index" : { "_index" : "books" } } -{"name": "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328} -{ "index" : { "_index" : "books" } } -{"name": "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227} -{ "index" : { "_index" : "books" } } -{"name": "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} -{ "index" : { "_index" : "books" } } -{"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311}`, -}; 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 607b85c7c6e7c..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' @@ -25,23 +25,29 @@ export const curlDefinition: LanguageDefinition = { configureClient: ({ apiKey, url }) => `export ES_URL="${url}" export API_KEY="${apiKey}"`, docLink: docLinks.restApis, + github: { + label: i18n.translate('xpack.enterpriseSearch.languages.cURL.githubLink', { + defaultMessage: 'curl', + }), + link: 'https://github.com/curl/curl', + }, 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: '', @@ -54,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 d75841a9ba1db..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,37 +11,52 @@ 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" -​ - "github.com/elastic/elasticsearch-serverless-go" + + "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', { + defaultMessage: 'go-elasticsearch', + }), + link: 'https://github.com/elastic/go-elasticsearch', + }, 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"}} @@ -53,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: '', @@ -62,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 033dc9b3169df..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' }); @@ -27,9 +27,15 @@ const client = new Client({ } });`, docLink: docLinks.clientsJsIntro, + github: { + label: i18n.translate('xpack.enterpriseSearch.languages.javascript.githubLink', { + defaultMessage: 'elasticsearch', + }), + link: 'https://github.com/elastic/elasticsearch-js', + }, 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}, @@ -40,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}' }}; } }); @@ -62,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 6b1abcae27954..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' ] @@ -25,13 +25,19 @@ print_r($response->asArray());`, ->setApiKey('${apiKey}') ->build();`, docLink: docLinks.clientsPhpOverview, + github: { + label: i18n.translate('xpack.enterpriseSearch.languages.php.githubLink', { + defaultMessage: 'elasticsearch-php', + }), + link: 'https://github.com/elastic/elasticsearch-php', + }, iconType: 'php.svg', id: Languages.PHP, - ingestData: `$params = [ + ingestData: ({ indexName }) => `$params = [ 'body' => [ [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780553351927', ], ], @@ -43,7 +49,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780441017225', ], ], @@ -55,7 +61,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780451524935', ], ], @@ -67,7 +73,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9781451673319', ], ], @@ -79,7 +85,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780060850524', ], ], @@ -91,7 +97,7 @@ print_r($response->asArray());`, ], [ 'index' => [ - '_index' => 'books', + '_index' => '${indexName}', '_id' => '9780385490818', ], ], @@ -112,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 c9d5ba67b26e4..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( @@ -19,20 +19,26 @@ client = Elasticsearch( api_key="${apiKey}" )`, docLink: docLinks.clientsPythonOverview, + github: { + label: i18n.translate('xpack.enterpriseSearch.languages.python.githubLink', { + defaultMessage: 'elasticsearch-py', + }), + link: 'https://github.com/elastic/elasticsearch-py', + }, 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}, ] @@ -46,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 6706323c96772..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,28 +11,35 @@ 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, + github: { + label: i18n.translate('xpack.enterpriseSearch.languages.ruby.githubLink', { + defaultMessage: 'elasticsearch-ruby', + }), + link: 'https://github.com/elastic/elasticsearch-ruby', + }, 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/components/getting_started/languages/utils.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/utils.ts deleted file mode 100644 index f973099a0947e..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/getting_started/languages/utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { LanguageDefinition, LanguageDefinitionSnippetArguments } from '@kbn/search-api-panels'; - -import { consoleDefinition } from './console'; - -export const showTryInConsole = (code: keyof LanguageDefinition) => code in consoleDefinition; - -export const getCodeSnippet = ( - language: Partial, - key: keyof LanguageDefinition, - args: LanguageDefinitionSnippetArguments -): string => { - const snippetVal = language[key]; - if (snippetVal === undefined) return ''; - if (typeof snippetVal === 'string') return snippetVal; - return snippetVal(args); -}; 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/connector_configuration_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts index 5fca8d70abdc5..fd13c0d55236c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts @@ -317,7 +317,7 @@ export const ConnectorConfigurationLogic = kea< return prev; }, {}), connectorId: values.index.connector.id, - indexName: values.index.connector.index_name, + indexName: values.index.connector.index_name ?? '', }); } }, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts index 563951fddf3eb..a2869f5a90963 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts @@ -79,7 +79,7 @@ export const ConnectorNameAndDescriptionLogic = kea< if (isConnectorIndex(values.index) || isCrawlerIndex(values.index)) { actions.makeRequest({ connectorId: values.index.connector.id, - indexName: values.index.connector.index_name, + indexName: values.index.connector.index_name ?? '', ...values.localNameAndDescription, }); } 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_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout.tsx index 8d97fb8e1863f..bf82d40d7585b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout.tsx @@ -33,6 +33,7 @@ import { CrawlCustomSettingsFlyoutCrawlTypeSelection } from './crawl_custom_sett import { CrawlCustomSettingsFlyoutDomainsPanelWithLogicProps } from './crawl_custom_settings_flyout_domains_panel'; import { CrawlCustomSettingsFlyoutLogic } from './crawl_custom_settings_flyout_logic'; import { CrawlCustomSettingsFlyoutMultipleCrawlDelete } from './crawl_custom_settings_flyout_multi_crawl_delete'; +import { CrawlCustomSettingsFlyoutMultiCrawlLogic } from './crawl_custom_settings_flyout_multi_crawl_logic'; import { CrawlCustomSettingsFlyoutMultipleCrawlTabs } from './crawl_custom_settings_flyout_multi_crawl_tabs'; import { CrawlCustomSettingsFlyoutMultiCrawlScheduling } from './crawl_custom_settings_flyout_mutli_crawl'; import { CrawlCustomSettingsFlyoutSeedUrlsPanelWithLogicProps } from './crawl_custom_settings_flyout_seed_urls_panel'; @@ -45,6 +46,7 @@ export const CrawlCustomSettingsFlyout: React.FC = () => { isSingleCrawlType, selectedDomainUrls, } = useValues(CrawlCustomSettingsFlyoutLogic); + const { crawlerCustomSchedulingIsValid } = useValues(CrawlCustomSettingsFlyoutMultiCrawlLogic); const { hideFlyout, startCustomCrawl, saveCustomSchedulingConfiguration } = useActions( CrawlCustomSettingsFlyoutLogic ); @@ -125,7 +127,11 @@ export const CrawlCustomSettingsFlyout: React.FC = () => { data-telemetry-id="entSearchContent-crawler-customCrawlSettings-startCrawl" fill onClick={submitFunctionLogic} - disabled={isDataLoading || selectedDomainUrls.length === 0} + disabled={ + isSingleCrawlType + ? isDataLoading || selectedDomainUrls.length === 0 + : !crawlerCustomSchedulingIsValid + } isLoading={isFormSubmitting} > {isSingleCrawlType diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domain_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domain_logic.test.ts new file mode 100644 index 0000000000000..5d350c34cbc91 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domain_logic.test.ts @@ -0,0 +1,197 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { LogicMounter, mockHttpValues } from '../../../../../__mocks__/kea_logic'; +import '../../_mocks_/index_name_logic.mock'; + +import { nextTick } from '@kbn/test-jest-helpers'; + +import { itShowsServerErrorAsFlashMessage } from '../../../../../test_helpers'; +import { DomainConfig } from '../../../../api/crawler/types'; + +import { CrawlCustomSettingsFlyoutDomainConfigLogic } from './crawl_custom_settings_flyout_domain_logic'; + +describe('CrawlCustomSettingsFlyoutDomainConfigLogic', () => { + const { mount } = new LogicMounter(CrawlCustomSettingsFlyoutDomainConfigLogic); + + const { http } = mockHttpValues; + + beforeEach(() => { + jest.clearAllMocks(); + mount(); + }); + + it('has expected default values', () => { + expect(CrawlCustomSettingsFlyoutDomainConfigLogic.values).toEqual({ + domainConfigMap: {}, + domainConfigs: [], + domainUrls: [], + }); + }); + + describe('actions', () => { + describe('fetchDomainConfigData', () => { + it('updates logic with data that has been converted from server to client', async () => { + jest.spyOn(CrawlCustomSettingsFlyoutDomainConfigLogic.actions, 'onRecieveDomainConfigData'); + + http.get.mockReturnValueOnce( + Promise.resolve({ + meta: { + page: { + current: 1, + size: 1, + total_pages: 2, + }, + }, + results: [ + { + id: '1234', + name: 'https://www.elastic.co', + seed_urls: [], + sitemap_urls: [], + }, + ], + }) + ); + + http.get.mockReturnValueOnce( + Promise.resolve({ + meta: { + page: { + current: 2, + size: 1, + total_pages: 2, + }, + }, + results: [ + { + id: '5678', + name: 'https://www.swiftype.com', + seed_urls: [], + sitemap_urls: [], + }, + ], + }) + ); + + CrawlCustomSettingsFlyoutDomainConfigLogic.actions.fetchDomainConfigData(); + await nextTick(); + + expect(http.get).toHaveBeenNthCalledWith( + 1, + '/internal/enterprise_search/indices/index-name/crawler/domain_configs', + { + query: { + 'page[current]': 1, + 'page[size]': 100, + }, + } + ); + expect(http.get).toHaveBeenNthCalledWith( + 2, + '/internal/enterprise_search/indices/index-name/crawler/domain_configs', + { + query: { + 'page[current]': 2, + 'page[size]': 1, + }, + } + ); + expect( + CrawlCustomSettingsFlyoutDomainConfigLogic.actions.onRecieveDomainConfigData + ).toHaveBeenCalledWith([ + { + id: '1234', + name: 'https://www.elastic.co', + seedUrls: [], + sitemapUrls: [], + }, + { + id: '5678', + name: 'https://www.swiftype.com', + seedUrls: [], + sitemapUrls: [], + }, + ]); + }); + + itShowsServerErrorAsFlashMessage(http.get, () => { + CrawlCustomSettingsFlyoutDomainConfigLogic.actions.fetchDomainConfigData(); + }); + }); + + describe('onRecieveDomainConfigData', () => { + it('saves the data', () => { + mount({ + domainConfigs: [], + }); + + CrawlCustomSettingsFlyoutDomainConfigLogic.actions.onRecieveDomainConfigData([ + { + name: 'https://www.elastic.co', + }, + ] as DomainConfig[]); + + expect(CrawlCustomSettingsFlyoutDomainConfigLogic.values.domainConfigs).toEqual([ + { + name: 'https://www.elastic.co', + }, + ]); + }); + }); + }); + + describe('selectors', () => { + beforeEach(() => { + mount({ + domainConfigs: [ + { + name: 'https://www.elastic.co', + sitemapUrls: [ + 'https://www.elastic.co/sitemap1.xml', + 'https://www.elastic.co/sitemap2.xml', + ], + seedUrls: ['https://www.elastic.co/', 'https://www.elastic.co/guide'], + }, + { + name: 'https://swiftype.com', + sitemapUrls: ['https://swiftype.com/sitemap1.xml', 'https://swiftype.com/sitemap2.xml'], + seedUrls: ['https://swiftype.com/', 'https://swiftype.com/documentation'], + }, + ], + }); + }); + + describe('domainUrls', () => { + it('contains all the domain urls from the domain config', () => { + expect(CrawlCustomSettingsFlyoutDomainConfigLogic.values.domainUrls).toEqual([ + 'https://www.elastic.co', + 'https://swiftype.com', + ]); + }); + }); + + describe('domainConfigMap', () => { + it('contains all the domain urls from the domain config', () => { + expect(CrawlCustomSettingsFlyoutDomainConfigLogic.values.domainConfigMap).toEqual({ + 'https://www.elastic.co': { + name: 'https://www.elastic.co', + sitemapUrls: [ + 'https://www.elastic.co/sitemap1.xml', + 'https://www.elastic.co/sitemap2.xml', + ], + seedUrls: ['https://www.elastic.co/', 'https://www.elastic.co/guide'], + }, + 'https://swiftype.com': { + name: 'https://swiftype.com', + sitemapUrls: ['https://swiftype.com/sitemap1.xml', 'https://swiftype.com/sitemap2.xml'], + seedUrls: ['https://swiftype.com/', 'https://swiftype.com/documentation'], + }, + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domain_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domain_logic.ts new file mode 100644 index 0000000000000..eaa72ddc831bb --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domain_logic.ts @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kea, MakeLogicType } from 'kea'; + +import { Meta } from '../../../../../../../common/types'; +import { flashAPIErrors } from '../../../../../shared/flash_messages'; +import { HttpLogic } from '../../../../../shared/http'; +import { DomainConfig, DomainConfigFromServer } from '../../../../api/crawler/types'; +import { domainConfigServerToClient } from '../../../../api/crawler/utils'; +import { IndexNameLogic } from '../../index_name_logic'; + +export interface CrawlCustomSettingsFlyoutDomainConfigLogicValues { + domainUrls: string[]; + domainConfigs: DomainConfig[]; + domainConfigMap: { + [key: string]: DomainConfig; + }; +} + +export const domainConfigsToDomainUrls = (domainConfigs: DomainConfig[]) => + domainConfigs.map((domainConfig) => domainConfig.name); + +export const domainConfigsToDomainConfigMap = (domainConfigs: DomainConfig[]) => + domainConfigs.reduce( + (acc, domainConfig) => ({ ...acc, [domainConfig.name]: domainConfig }), + {} as { [key: string]: DomainConfig } + ); + +export interface CrawlCustomSettingsFlyoutDomainConfigLogicActions { + fetchDomainConfigData(): void; + onRecieveDomainConfigData(domainConfigs: DomainConfig[]): { domainConfigs: DomainConfig[] }; +} + +export const CrawlCustomSettingsFlyoutDomainConfigLogic = kea< + MakeLogicType< + CrawlCustomSettingsFlyoutDomainConfigLogicValues, + CrawlCustomSettingsFlyoutDomainConfigLogicActions + > +>({ + path: ['enterprise_search', 'crawler', 'crawl_custom_settings_flyout_domain_logic'], + actions: () => ({ + fetchDomainConfigData: true, + onRecieveDomainConfigData: (domainConfigs) => ({ domainConfigs }), + }), + reducers: () => ({ + domainConfigs: [ + [], + { + onRecieveDomainConfigData: (_, { domainConfigs }) => domainConfigs, + }, + ], + }), + selectors: () => ({ + domainUrls: [ + (selectors) => [selectors.domainConfigs], + (domainConfigs: DomainConfig[]) => domainConfigsToDomainUrls(domainConfigs), + ], + domainConfigMap: [ + (selectors) => [selectors.domainConfigs], + (domainConfigs: DomainConfig[]) => domainConfigsToDomainConfigMap(domainConfigs), + ], + }), + listeners: ({ actions }) => ({ + fetchDomainConfigData: async () => { + const { http } = HttpLogic.values; + const { indexName } = IndexNameLogic.values; + + let domainConfigs: DomainConfig[] = []; + let totalPages: number = 1; + let nextPage: number = 1; + let pageSize: number = 100; + + try { + while (nextPage <= totalPages) { + const { + results, + meta: { page }, + } = await http.get<{ + meta: Meta; + results: DomainConfigFromServer[]; + }>(`/internal/enterprise_search/indices/${indexName}/crawler/domain_configs`, { + query: { 'page[current]': nextPage, 'page[size]': pageSize }, + }); + + domainConfigs = [...domainConfigs, ...results.map(domainConfigServerToClient)]; + + nextPage = page.current + 1; + totalPages = page.total_pages; + pageSize = page.size; + } + + actions.onRecieveDomainConfigData(domainConfigs); + } catch (e) { + flashAPIErrors(e); + } + }, + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.tsx index ea9f07252128e..a4faa76b8a6c4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.tsx @@ -24,6 +24,7 @@ import { i18n } from '@kbn/i18n'; import { SimplifiedSelectable } from '../../../../../shared/simplified_selectable/simplified_selectable'; +import { CrawlCustomSettingsFlyoutDomainConfigLogic } from './crawl_custom_settings_flyout_domain_logic'; import { CrawlCustomSettingsFlyoutLogic } from './crawl_custom_settings_flyout_logic'; interface CrawlCustomSettingsFlyoutDomainsPanelProps { @@ -33,7 +34,8 @@ interface CrawlCustomSettingsFlyoutDomainsPanelProps { } export const CrawlCustomSettingsFlyoutDomainsPanelWithLogicProps: React.FC = () => { - const { domainUrls, selectedDomainUrls } = useValues(CrawlCustomSettingsFlyoutLogic); + const { selectedDomainUrls } = useValues(CrawlCustomSettingsFlyoutLogic); + const { domainUrls } = useValues(CrawlCustomSettingsFlyoutDomainConfigLogic); const { onSelectDomainUrls } = useActions(CrawlCustomSettingsFlyoutLogic); return ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_logic.test.ts index 64f4081479d83..a0f090cf6dfcc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_logic.test.ts @@ -4,58 +4,43 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { LogicMounter, mockHttpValues } from '../../../../../__mocks__/kea_logic'; -import '../../_mocks_/index_name_logic.mock'; +import { LogicMounter } from '../../../../../__mocks__/kea_logic'; import { nextTick } from '@kbn/test-jest-helpers'; -import { itShowsServerErrorAsFlashMessage } from '../../../../../test_helpers'; -import { StartSyncApiLogic } from '../../../../api/connector/start_sync_api_logic'; -import { DomainConfig } from '../../../../api/crawler/types'; -import { CachedFetchIndexApiLogic } from '../../../../api/index/cached_fetch_index_api_logic'; +import { DomainConfig, CustomCrawlType } from '../../../../api/crawler/types'; import { IndexNameLogic } from '../../index_name_logic'; import { IndexViewLogic } from '../../index_view_logic'; import { CrawlerLogic } from '../crawler_logic'; +import { CrawlCustomSettingsFlyoutDomainConfigLogic } from './crawl_custom_settings_flyout_domain_logic'; import { CrawlCustomSettingsFlyoutLogic } from './crawl_custom_settings_flyout_logic'; -import { CrawlCustomSettingsFlyoutMultiCrawlLogic } from './crawl_custom_settings_flyout_multi_crawl_logic'; -// Temporarily skipping the tests before FF, the error results from connected kea logic. -// They will be fixed as a separate ticket. -describe.skip('CrawlCustomSettingsFlyoutLogic', () => { +describe('CrawlCustomSettingsFlyoutLogic', () => { const { mount } = new LogicMounter(CrawlCustomSettingsFlyoutLogic); - const { mount: multiCrawlLogicMount } = new LogicMounter( - CrawlCustomSettingsFlyoutMultiCrawlLogic - ); const { mount: indexViewLogicMount } = new LogicMounter(IndexViewLogic); - const { mount: apiLogicMount } = new LogicMounter(StartSyncApiLogic); - const { mount: fetchIndexMount } = new LogicMounter(CachedFetchIndexApiLogic); const { mount: indexNameMount } = new LogicMounter(IndexNameLogic); - const { http } = mockHttpValues; - beforeEach(() => { jest.clearAllMocks(); - indexNameMount(); - apiLogicMount(); - fetchIndexMount(); indexViewLogicMount(); - multiCrawlLogicMount(); + indexNameMount(); mount(); }); it('has expected default values', () => { expect(CrawlCustomSettingsFlyoutLogic.values).toEqual({ + crawlType: CustomCrawlType.ONE_TIME, customEntryPointUrls: [], customSitemapUrls: [], domainConfigMap: {}, domainConfigs: [], - domainUrls: [], entryPointUrls: [], includeSitemapsInRobotsTxt: true, isDataLoading: true, isFlyoutVisible: false, isFormSubmitting: false, + isSingleCrawlType: true, maxCrawlDepth: 2, selectedDomainUrls: [], selectedEntryPointUrls: [], @@ -65,96 +50,6 @@ describe.skip('CrawlCustomSettingsFlyoutLogic', () => { }); describe('actions', () => { - describe('fetchDomainConfigData', () => { - it('updates logic with data that has been converted from server to client', async () => { - jest.spyOn(CrawlCustomSettingsFlyoutLogic.actions, 'onRecieveDomainConfigData'); - - http.get.mockReturnValueOnce( - Promise.resolve({ - meta: { - page: { - current: 1, - size: 1, - total_pages: 2, - }, - }, - results: [ - { - id: '1234', - name: 'https://www.elastic.co', - seed_urls: [], - sitemap_urls: [], - }, - ], - }) - ); - - http.get.mockReturnValueOnce( - Promise.resolve({ - meta: { - page: { - current: 2, - size: 1, - total_pages: 2, - }, - }, - results: [ - { - id: '5678', - name: 'https://www.swiftype.com', - seed_urls: [], - sitemap_urls: [], - }, - ], - }) - ); - - CrawlCustomSettingsFlyoutLogic.actions.fetchDomainConfigData(); - await nextTick(); - - expect(http.get).toHaveBeenNthCalledWith( - 1, - '/internal/enterprise_search/indices/index-name/crawler/domain_configs', - { - query: { - 'page[current]': 1, - 'page[size]': 100, - }, - } - ); - expect(http.get).toHaveBeenNthCalledWith( - 2, - '/internal/enterprise_search/indices/index-name/crawler/domain_configs', - { - query: { - 'page[current]': 2, - 'page[size]': 1, - }, - } - ); - expect( - CrawlCustomSettingsFlyoutLogic.actions.onRecieveDomainConfigData - ).toHaveBeenCalledWith([ - { - id: '1234', - name: 'https://www.elastic.co', - seedUrls: [], - sitemapUrls: [], - }, - { - id: '5678', - name: 'https://www.swiftype.com', - seedUrls: [], - sitemapUrls: [], - }, - ]); - }); - - itShowsServerErrorAsFlashMessage(http.get, () => { - CrawlCustomSettingsFlyoutLogic.actions.fetchDomainConfigData(); - }); - }); - describe('hideFlyout', () => { it('hides the modal', () => { CrawlCustomSettingsFlyoutLogic.actions.hideFlyout(); @@ -443,53 +338,27 @@ describe.skip('CrawlCustomSettingsFlyoutLogic', () => { describe('selectors', () => { beforeEach(() => { + jest.clearAllMocks(); mount({ - domainConfigs: [ - { - name: 'https://www.elastic.co', - sitemapUrls: [ - 'https://www.elastic.co/sitemap1.xml', - 'https://www.elastic.co/sitemap2.xml', - ], - seedUrls: ['https://www.elastic.co/', 'https://www.elastic.co/guide'], - }, - { - name: 'https://swiftype.com', - sitemapUrls: ['https://swiftype.com/sitemap1.xml', 'https://swiftype.com/sitemap2.xml'], - seedUrls: ['https://swiftype.com/', 'https://swiftype.com/documentation'], - }, - ], selectedDomainUrls: ['https://swiftype.com'], }); - }); - - describe('domainUrls', () => { - it('contains all the domain urls from the domain config', () => { - expect(CrawlCustomSettingsFlyoutLogic.values.domainUrls).toEqual([ - 'https://www.elastic.co', - 'https://swiftype.com', - ]); - }); - }); - - describe('domainConfigMap', () => { - it('contains all the domain urls from the domain config', () => { - expect(CrawlCustomSettingsFlyoutLogic.values.domainConfigMap).toEqual({ - 'https://www.elastic.co': { - name: 'https://www.elastic.co', - sitemapUrls: [ - 'https://www.elastic.co/sitemap1.xml', - 'https://www.elastic.co/sitemap2.xml', - ], - seedUrls: ['https://www.elastic.co/', 'https://www.elastic.co/guide'], - }, - 'https://swiftype.com': { - name: 'https://swiftype.com', - sitemapUrls: ['https://swiftype.com/sitemap1.xml', 'https://swiftype.com/sitemap2.xml'], - seedUrls: ['https://swiftype.com/', 'https://swiftype.com/documentation'], - }, - }); - }); + CrawlCustomSettingsFlyoutDomainConfigLogic.actions.onRecieveDomainConfigData([ + { + id: '1', + name: 'https://www.elastic.co', + sitemapUrls: [ + 'https://www.elastic.co/sitemap1.xml', + 'https://www.elastic.co/sitemap2.xml', + ], + seedUrls: ['https://www.elastic.co/', 'https://www.elastic.co/guide'], + }, + { + id: '2', + name: 'https://swiftype.com', + sitemapUrls: ['https://swiftype.com/sitemap1.xml', 'https://swiftype.com/sitemap2.xml'], + seedUrls: ['https://swiftype.com/', 'https://swiftype.com/documentation'], + }, + ]); }); describe('entryPointUrls', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_logic.ts index cae406b4c5b68..6a01e5b792f5f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_logic.ts @@ -7,21 +7,13 @@ import { kea, MakeLogicType } from 'kea'; -import { Meta } from '../../../../../../../common/types'; -import { flashAPIErrors } from '../../../../../shared/flash_messages'; -import { HttpLogic } from '../../../../../shared/http'; -import { - CustomCrawlType, - DomainConfig, - DomainConfigFromServer, - CrawlerCustomSchedule, -} from '../../../../api/crawler/types'; -import { domainConfigServerToClient } from '../../../../api/crawler/utils'; -import { IndexNameLogic } from '../../index_name_logic'; +import { CustomCrawlType, DomainConfig } from '../../../../api/crawler/types'; import { CrawlerActions, CrawlerLogic, CrawlRequestOverrides } from '../crawler_logic'; import { extractDomainAndEntryPointFromUrl } from '../domain_management/add_domain/utils'; +import { CrawlCustomSettingsFlyoutDomainConfigLogic } from './crawl_custom_settings_flyout_domain_logic'; + import { CrawlCustomSettingsFlyoutMultiCrawlLogic } from './crawl_custom_settings_flyout_multi_crawl_logic'; export interface CrawlCustomSettingsFlyoutLogicValues { @@ -44,9 +36,6 @@ export interface CrawlCustomSettingsFlyoutLogicValues { selectedEntryPointUrls: string[]; selectedSitemapUrls: string[]; sitemapUrls: string[]; - crawlerConfigurations: CrawlerCustomSchedule[]; - multiCrawlerSitemapUrls: string[][]; - multiCrawlerEntryPointUrls: string[][]; } export interface CrawlCustomSettingsFlyoutLogicActions { @@ -89,16 +78,16 @@ export const CrawlCustomSettingsFlyoutLogic = kea< actions: [ CrawlerLogic, ['startCrawl'], + CrawlCustomSettingsFlyoutDomainConfigLogic, + ['fetchDomainConfigData', 'onRecieveDomainConfigData'], CrawlCustomSettingsFlyoutMultiCrawlLogic, ['fetchCustomScheduling', 'postCustomScheduling'], ], - values: [CrawlCustomSettingsFlyoutMultiCrawlLogic, ['crawlerConfigurations']], + values: [CrawlCustomSettingsFlyoutDomainConfigLogic, ['domainConfigs', 'domainConfigMap']], }, actions: () => ({ - fetchDomainConfigData: true, saveCustomSchedulingConfiguration: true, hideFlyout: true, - onRecieveDomainConfigData: (domainConfigs) => ({ domainConfigs }), onSelectCrawlType: (crawlType) => ({ crawlType }), onSelectCustomEntryPointUrls: (entryPointUrls) => ({ entryPointUrls }), onSelectCustomSitemapUrls: (sitemapUrls) => ({ sitemapUrls }), @@ -131,12 +120,6 @@ export const CrawlCustomSettingsFlyoutLogic = kea< onSelectCustomSitemapUrls: (_, { sitemapUrls }) => sitemapUrls, }, ], - domainConfigs: [ - [], - { - onRecieveDomainConfigData: (_, { domainConfigs }) => domainConfigs, - }, - ], includeSitemapsInRobotsTxt: [ true, { @@ -202,20 +185,11 @@ export const CrawlCustomSettingsFlyoutLogic = kea< ], }), selectors: () => ({ - domainUrls: [ - (selectors) => [selectors.domainConfigs], - (domainConfigs: DomainConfig[]) => domainConfigs.map((domainConfig) => domainConfig.name), - ], - domainConfigMap: [ - (selectors) => [selectors.domainConfigs], - (domainConfigs: DomainConfig[]) => - domainConfigs.reduce( - (acc, domainConfig) => ({ ...acc, [domainConfig.name]: domainConfig }), - {} as { [key: string]: DomainConfig } - ), - ], entryPointUrls: [ - (selectors) => [selectors.domainConfigMap, selectors.selectedDomainUrls], + (selectors) => [ + CrawlCustomSettingsFlyoutDomainConfigLogic.selectors.domainConfigMap, + selectors.selectedDomainUrls, + ], (domainConfigMap: { [key: string]: DomainConfig }, selectedDomainUrls: string[]): string[] => selectedDomainUrls.flatMap( (selectedDomainUrl) => domainConfigMap[selectedDomainUrl].seedUrls @@ -226,72 +200,18 @@ export const CrawlCustomSettingsFlyoutLogic = kea< (crawlType: string): boolean => crawlType === CustomCrawlType.ONE_TIME, ], sitemapUrls: [ - (selectors) => [selectors.domainConfigMap, selectors.selectedDomainUrls], + (selectors) => [ + CrawlCustomSettingsFlyoutDomainConfigLogic.selectors.domainConfigMap, + selectors.selectedDomainUrls, + ], (domainConfigMap: { [key: string]: DomainConfig }, selectedDomainUrls: string[]): string[] => selectedDomainUrls.flatMap( (selectedDomainUrl) => domainConfigMap[selectedDomainUrl].sitemapUrls ), ], - multiCrawlerEntryPointUrls: [ - (selectors) => [selectors.domainConfigMap, selectors.crawlerConfigurations], - ( - domainConfigMap: { [key: string]: DomainConfig }, - crawlerConfigs: CrawlerCustomSchedule[] - ): string[][] => - crawlerConfigs.map((c) => - c.selectedDomainUrls.flatMap( - (selectedDomainUrl) => domainConfigMap[selectedDomainUrl].seedUrls - ) - ), - ], - multiCrawlerSitemapUrls: [ - (selectors) => [selectors.domainConfigMap, selectors.crawlerConfigurations], - ( - domainConfigMap: { [key: string]: DomainConfig }, - crawlerConfigs: CrawlerCustomSchedule[] - ): string[][] => - crawlerConfigs.map((c) => - c.selectedDomainUrls.flatMap( - (selectedDomainUrl) => domainConfigMap[selectedDomainUrl].sitemapUrls - ) - ), - ], }), listeners: ({ actions, values }) => ({ - fetchDomainConfigData: async () => { - const { http } = HttpLogic.values; - const { indexName } = IndexNameLogic.values; - - let domainConfigs: DomainConfig[] = []; - let totalPages: number = 1; - let nextPage: number = 1; - let pageSize: number = 100; - - try { - while (nextPage <= totalPages) { - const { - results, - meta: { page }, - } = await http.get<{ - meta: Meta; - results: DomainConfigFromServer[]; - }>(`/internal/enterprise_search/indices/${indexName}/crawler/domain_configs`, { - query: { 'page[current]': nextPage, 'page[size]': pageSize }, - }); - - domainConfigs = [...domainConfigs, ...results.map(domainConfigServerToClient)]; - - nextPage = page.current + 1; - totalPages = page.total_pages; - pageSize = page.size; - } - - actions.onRecieveDomainConfigData(domainConfigs); - } catch (e) { - flashAPIErrors(e); - } - }, - showFlyout: () => { + showFlyout: async () => { actions.fetchDomainConfigData(); actions.fetchCustomScheduling(); }, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_multi_crawl_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_multi_crawl_logic.ts index 0b03ea6791fb8..aa98f838a8e18 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_multi_crawl_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_multi_crawl_logic.ts @@ -8,14 +8,13 @@ import { kea, MakeLogicType } from 'kea'; import { ConnectorScheduling } from '../../../../../../../common/types/connectors'; -import { - CrawlerCustomSchedulesServer, - CrawlerCustomScheduleClient, -} from '../../../../../../../common/types/crawler'; +import { CrawlerCustomSchedulesServer } from '../../../../../../../common/types/crawler'; + import { CrawlerIndex } from '../../../../../../../common/types/indices'; +import { Actions } from '../../../../../shared/api_logic/create_api_logic'; import { flashAPIErrors } from '../../../../../shared/flash_messages'; import { HttpLogic } from '../../../../../shared/http'; -import { CrawlerCustomSchedule } from '../../../../api/crawler/types'; +import { DomainConfig, CrawlerCustomSchedule } from '../../../../api/crawler/types'; import { crawlerCustomSchedulingServerToClient, crawlerCustomSchedulingClientToServer, @@ -24,15 +23,33 @@ import { IndexNameLogic } from '../../index_name_logic'; import { IndexViewLogic } from '../../index_view_logic'; +import { + CrawlCustomSettingsFlyoutDomainConfigLogic, + domainConfigsToDomainConfigMap, +} from './crawl_custom_settings_flyout_domain_logic'; + import { filterSeedUrlsByDomainUrls } from './crawl_custom_settings_flyout_logic'; +import { + PostCustomSchedulingApiLogic, + PostCustomSchedulingArgs, +} from './crawl_custom_settings_flyout_schedule_api_logic'; -export interface CrawlCustomSettingsFlyoutLogicValues { +export interface CrawlCustomSettingsFlyoutMultiCrawlLogicValues { crawlerConfigActiveTab: number; crawlerConfigurations: CrawlerCustomSchedule[]; + crawlerConfigurationsWithDomainData: CrawlerCustomSchedule[]; index: CrawlerIndex; + domainUrls: string[]; + domainConfigs: DomainConfig[]; + domainConfigMap: { + [key: string]: DomainConfig; + }; + crawlerCustomSchedulingIsValid: boolean; } -export interface CrawlCustomSettingsFlyoutLogicActions { +type PostCustomSchedulingApiValues = Actions; + +export interface CrawlCustomSettingsFlyoutMultiCrawlLogicActions { fetchCustomScheduling(): void; postCustomScheduling(): void; onReceiveCrawlerCustomScheduling(crawlerConfigurations: CrawlerCustomSchedule[]): { @@ -79,9 +96,11 @@ export interface CrawlCustomSettingsFlyoutLogicActions { enabled: boolean; }; toggleIncludeSitemapsInRobotsTxt(index: number): { index: number }; + makePostCustomSchedulingRequest: PostCustomSchedulingApiValues['makeRequest']; } const defaulCrawlerConfiguration: CrawlerCustomSchedule = { + scheduleKey: 'crawler_0', name: 'Crawler 0', maxCrawlDepth: 2, customEntryPointUrls: [], @@ -90,16 +109,32 @@ const defaulCrawlerConfiguration: CrawlerCustomSchedule = { selectedDomainUrls: [], selectedEntryPointUrls: [], selectedSitemapUrls: [], - interval: '* * * * *', + interval: '0 0 0 * * ?', enabled: false, + sitemapUrls: [], + entryPointUrls: [], }; export const CrawlCustomSettingsFlyoutMultiCrawlLogic = kea< - MakeLogicType + MakeLogicType< + CrawlCustomSettingsFlyoutMultiCrawlLogicValues, + CrawlCustomSettingsFlyoutMultiCrawlLogicActions + > >({ path: ['enterprise_search', 'crawler', 'crawl_custom_settings_flyout_multi_crawl_logic'], connect: { - values: [IndexViewLogic, ['index']], + actions: [ + PostCustomSchedulingApiLogic, + ['makeRequest as makePostCustomSchedulingRequest'], + CrawlCustomSettingsFlyoutDomainConfigLogic, + ['onRecieveDomainConfigData'], + ], + values: [ + IndexViewLogic, + ['index'], + CrawlCustomSettingsFlyoutDomainConfigLogic, + ['domainConfigs', 'domainConfigMap'], + ], }, actions: () => ({ fetchCustomScheduling: true, @@ -130,15 +165,36 @@ export const CrawlCustomSettingsFlyoutMultiCrawlLogic = kea< [defaulCrawlerConfiguration], { onReceiveCrawlerCustomScheduling: (_, { crawlerConfigurations }) => { - return crawlerConfigurations.map((configuration) => ({ - ...defaulCrawlerConfiguration, - ...configuration, - })); + // Handle case with no custom scheduling returned from server + return crawlerConfigurations.length > 0 + ? crawlerConfigurations.map((configuration) => ({ + ...defaulCrawlerConfiguration, + ...configuration, + })) + : [defaulCrawlerConfiguration]; + }, + onAddCustomCrawler: (state, { index }) => { + let newScheduleKey = `crawler_${index}`; + let suffix = index; + + // Check if the newScheduleKey already exists in the array + const existingKeys = state.map((crawler) => crawler.scheduleKey); + if (existingKeys.includes(newScheduleKey)) { + // Handle the case where a duplicate scheduleKey is found + while (existingKeys.includes(`${newScheduleKey}_${suffix}`)) { + suffix++; + } + newScheduleKey = `${newScheduleKey}_${suffix}`; + } + return [ + ...state, + { + ...defaulCrawlerConfiguration, + name: `Crawler ${suffix}`, + scheduleKey: newScheduleKey, + }, + ]; }, - onAddCustomCrawler: (state, { index }) => [ - ...state, - { ...defaulCrawlerConfiguration, name: `Crawler ${index}` }, - ], onDeleteCustomCrawler: (state, { index }) => { return state.filter((_, i) => i !== index); }, @@ -197,9 +253,70 @@ export const CrawlCustomSettingsFlyoutMultiCrawlLogic = kea< const { interval } = newSchedule; return state.map((crawler, i) => (i === index ? { ...crawler, interval } : crawler)); }, + onRecieveDomainConfigData: (state, { domainConfigs }) => { + const domainConfigsMap = domainConfigsToDomainConfigMap(domainConfigs); + return state.map((crawler) => { + const entryPointUrls = crawler.selectedDomainUrls.flatMap( + (selectedDomainUrl) => domainConfigsMap[selectedDomainUrl].seedUrls + ); + const selectedEntryPointUrls = crawler.customEntryPointUrls.filter((entryPointUrl) => + entryPointUrls.includes(entryPointUrl) + ); + const customEntryPointUrls = crawler.customEntryPointUrls.filter( + (entryPointUrl) => !entryPointUrls.includes(entryPointUrl) + ); + const sitemapUrls = crawler.selectedDomainUrls.flatMap( + (selectedDomainUrl) => domainConfigsMap[selectedDomainUrl].sitemapUrls + ); + const selectedSitemapUrls = crawler.customSitemapUrls.filter((sitemapUrl) => + sitemapUrls.includes(sitemapUrl) + ); + const customSitemapUrls = crawler.customSitemapUrls.filter( + (sitemapUrl) => !sitemapUrls.includes(sitemapUrl) + ); + + return { + ...crawler, + entryPointUrls, + selectedEntryPointUrls, + customEntryPointUrls, + sitemapUrls, + selectedSitemapUrls, + customSitemapUrls, + }; + }); + }, }, ], }), + selectors: () => ({ + crawlerConfigurationsWithDomainData: [ + (selectors) => [selectors.domainConfigMap, selectors.crawlerConfigurations], + ( + domainConfigMap: { [key: string]: DomainConfig }, + crawlerConfigs: CrawlerCustomSchedule[] + ): CrawlerCustomSchedule[] => + crawlerConfigs.map((crawlerConfig) => { + const entryPointUrls = crawlerConfig.selectedDomainUrls.flatMap( + (selectedDomainUrl) => domainConfigMap[selectedDomainUrl].seedUrls + ); + const sitemapUrls = crawlerConfig.selectedDomainUrls.flatMap( + (selectedDomainUrl) => domainConfigMap[selectedDomainUrl].sitemapUrls + ); + + return { + ...crawlerConfig, + entryPointUrls, + sitemapUrls, + }; + }), + ], + crawlerCustomSchedulingIsValid: [ + (selectors) => [selectors.crawlerConfigurations], + (crawlerConfigs: CrawlerCustomSchedule[]): boolean => + crawlerConfigs.every((config) => config.selectedDomainUrls.length > 0), + ], + }), listeners: ({ actions, values }) => ({ fetchCustomScheduling: async () => { const { http } = HttpLogic.values; @@ -216,15 +333,11 @@ export const CrawlCustomSettingsFlyoutMultiCrawlLogic = kea< } }, postCustomScheduling: async () => { - const { http } = HttpLogic.values; const { indexName } = IndexNameLogic.values; const { crawlerConfigurations } = values; const customScheduling = crawlerCustomSchedulingClientToServer(crawlerConfigurations); try { - await http.post( - `/internal/enterprise_search/indices/${indexName}/crawler/custom_scheduling`, - { body: JSON.stringify(Object.fromEntries(customScheduling)) } - ); + actions.makePostCustomSchedulingRequest({ indexName, customScheduling }); } catch (e) { flashAPIErrors(e); } diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_multi_crawl_tabs.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_multi_crawl_tabs.tsx index 90871ff20b954..638364a83e480 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_multi_crawl_tabs.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_multi_crawl_tabs.tsx @@ -31,7 +31,7 @@ export const CrawlCustomSettingsFlyoutMultipleCrawlTabs: React.FC = () => { ); const crawlerTabData = crawlerConfigurations.map((_, index) => ({ - key: `crawl_${index}`, + key: `crawler_${index}`, index, label: `${CRAWLER_TAB_PREFIX} ${index + 1}`, })); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_mutli_crawl.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_mutli_crawl.tsx index 2548223181ad8..5b37a26ed1f8f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_mutli_crawl.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_mutli_crawl.tsx @@ -13,18 +13,16 @@ import { EuiSpacer } from '@elastic/eui'; import { CrawlCustomSettingsFlyoutCrawlDepthPanel } from './crawl_custom_settings_flyout_crawl_depth_panel'; import { MultiCrawlScheduler } from './crawl_custom_settings_flyout_crawl_scheduler'; +import { CrawlCustomSettingsFlyoutDomainConfigLogic } from './crawl_custom_settings_flyout_domain_logic'; import { CrawlCustomSettingsFlyoutDomainsPanel } from './crawl_custom_settings_flyout_domains_panel'; -import { CrawlCustomSettingsFlyoutLogic } from './crawl_custom_settings_flyout_logic'; import { CrawlCustomSettingsFlyoutMultiCrawlLogic } from './crawl_custom_settings_flyout_multi_crawl_logic'; import { CrawlCustomSettingsFlyoutSeedUrlsPanel } from './crawl_custom_settings_flyout_seed_urls_panel'; export const CrawlCustomSettingsFlyoutMultiCrawlScheduling: React.FC = () => { - const { domainUrls, multiCrawlerEntryPointUrls, multiCrawlerSitemapUrls } = useValues( - CrawlCustomSettingsFlyoutLogic - ); + const { domainUrls } = useValues(CrawlCustomSettingsFlyoutDomainConfigLogic); const { - crawlerConfigurations, + crawlerConfigurationsWithDomainData, crawlerConfigActiveTab, index: crawlerIndex, } = useValues(CrawlCustomSettingsFlyoutMultiCrawlLogic); @@ -43,7 +41,7 @@ export const CrawlCustomSettingsFlyoutMultiCrawlScheduling: React.FC = () => { return ( <> - {crawlerConfigurations.map((config, index) => { + {crawlerConfigurationsWithDomainData.map((config, index) => { if (index === crawlerConfigActiveTab) { return ( @@ -65,8 +63,6 @@ export const CrawlCustomSettingsFlyoutMultiCrawlScheduling: React.FC = () => { onSelectEntryPointUrls={(e) => onSelectEntryPointUrls(index, e)} onSelectSitemapUrls={(e) => onSelectSitemapUrls(index, e)} toggleIncludeSitemapsInRobotsTxt={() => toggleIncludeSitemapsInRobotsTxt(index)} - entryPointUrls={multiCrawlerEntryPointUrls[index]} - sitemapUrls={multiCrawlerSitemapUrls[index]} /> { + const route = `/internal/enterprise_search/indices/${indexName}/crawler/custom_scheduling`; + await HttpLogic.values.http.post(route, { + body: JSON.stringify(Object.fromEntries(customScheduling)), + }); +}; + +export const PostCustomSchedulingApiLogic = createApiLogic( + ['post_crawler_custom_scheduling_api_logic'], + postCrawlerCustomScheduling, + { + showSuccessFlashFn: () => + i18n.translate( + 'xpack.enterpriseSearch.crawler.crawlCustomSettingsFlyout.postCrawlerCustomSchedulingSuccess.message', + { + defaultMessage: 'Successfully saved crawler custom scheduling.', + } + ), + } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.test.tsx index 0d7fe0eb5c049..d60df4c0cdb75 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.test.tsx @@ -71,14 +71,14 @@ describe('CrawlCustomSettingsFlyoutSeedUrlsPanel', () => { selectedDomainUrls: MOCK_VALUES.selectedDomainUrls, selectedEntryPointUrls: MOCK_VALUES.selectedEntryPointUrls, selectedSitemapUrls: MOCK_VALUES.selectedSitemapUrls, + entryPointUrls: MOCK_VALUES.entryPointUrls, + sitemapUrls: MOCK_VALUES.sitemapUrls, }} onSelectCustomEntryPointUrls={MOCK_ACTIONS.onSelectCustomEntryPointUrls} onSelectCustomSitemapUrls={MOCK_ACTIONS.onSelectCustomSitemapUrls} onSelectEntryPointUrls={MOCK_ACTIONS.onSelectEntryPointUrls} onSelectSitemapUrls={MOCK_ACTIONS.onSelectSitemapUrls} toggleIncludeSitemapsInRobotsTxt={MOCK_ACTIONS.toggleIncludeSitemapsInRobotsTxt} - entryPointUrls={MOCK_VALUES.entryPointUrls} - sitemapUrls={MOCK_VALUES.sitemapUrls} /> ); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.tsx index ce299b9e0ca11..215e004b94818 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.tsx @@ -41,6 +41,8 @@ type CrawlerCustomScheduleConfig = Pick< | 'selectedDomainUrls' | 'selectedEntryPointUrls' | 'selectedSitemapUrls' + | 'entryPointUrls' + | 'sitemapUrls' >; interface CrawlCustomSettingsFlyoutSeedUrlsPanelProps { @@ -50,8 +52,6 @@ interface CrawlCustomSettingsFlyoutSeedUrlsPanelProps { onSelectEntryPointUrls: (urls: string[]) => void; onSelectSitemapUrls: (urls: string[]) => void; toggleIncludeSitemapsInRobotsTxt: () => void; - entryPointUrls: string[]; - sitemapUrls: string[]; } export const CrawlCustomSettingsFlyoutSeedUrlsPanelWithLogicProps: React.FC = () => { @@ -80,6 +80,8 @@ export const CrawlCustomSettingsFlyoutSeedUrlsPanelWithLogicProps: React.FC = () selectedDomainUrls, selectedEntryPointUrls, selectedSitemapUrls, + entryPointUrls, + sitemapUrls, }; return ( @@ -90,8 +92,6 @@ export const CrawlCustomSettingsFlyoutSeedUrlsPanelWithLogicProps: React.FC = () onSelectEntryPointUrls={onSelectEntryPointUrls} onSelectSitemapUrls={onSelectSitemapUrls} toggleIncludeSitemapsInRobotsTxt={toggleIncludeSitemapsInRobotsTxt} - entryPointUrls={entryPointUrls} - sitemapUrls={sitemapUrls} /> ); }; @@ -105,8 +105,6 @@ export const CrawlCustomSettingsFlyoutSeedUrlsPanel: React.FC< onSelectEntryPointUrls, onSelectSitemapUrls, toggleIncludeSitemapsInRobotsTxt, - entryPointUrls, - sitemapUrls, }) => { const totalSeedUrls = scheduleConfig.customEntryPointUrls.length + @@ -187,7 +185,7 @@ export const CrawlCustomSettingsFlyoutSeedUrlsPanel: React.FC< { const indexToShow = selectedIndexType === 'content-index' ? indexName - : indexName.replace('search-', CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX); + : stripSearchPrefix(indexName, CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX); const mappingLogic = mappingsWithPropsApiLogic(indexToShow); const documentLogic = searchDocumentsApiLogic(indexToShow); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_mappings.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_mappings.tsx index 24f126efebbad..df040a56cfda5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_mappings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_mappings.tsx @@ -26,6 +26,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX } from '../../../../../common/constants'; +import { stripSearchPrefix } from '../../../../../common/utils/strip_search_prefix'; import { docLinks } from '../../../shared/doc_links'; @@ -52,7 +53,7 @@ export const SearchIndexIndexMappings: React.FC = () => { const indexToShow = selectedIndexType === 'content-index' ? indexName - : indexName.replace('search-', CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX); + : stripSearchPrefix(indexName, CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX); const { makeRequest: makeMappingRequest } = useActions(mappingsWithPropsApiLogic(indexToShow)); const { data: mappingData } = useValues(mappingsWithPropsApiLogic(indexToShow)); const shouldShowAccessControlSwitch = 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/public/applications/shared/doc_links/doc_links.ts b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts index 377d2f9ccd71d..12150de94bde3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts @@ -410,6 +410,7 @@ class DocLinks { this.connectorsOracle = docLinks.links.enterpriseSearch.connectorsOracle; this.connectorsPostgreSQL = docLinks.links.enterpriseSearch.connectorsPostgreSQL; this.connectorsS3 = docLinks.links.enterpriseSearch.connectorsS3; + this.connectorsSalesforce = docLinks.links.enterpriseSearch.connectorsSalesforce; this.connectorsServiceNow = docLinks.links.enterpriseSearch.connectorsServiceNow; this.connectorsSharepoint = docLinks.links.enterpriseSearch.connectorsSharepoint; this.connectorsSharepointOnline = docLinks.links.enterpriseSearch.connectorsSharepointOnline; diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index e0b86110125fb..ecdf553b8eabe 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -121,8 +121,11 @@ export class EnterpriseSearchPlugin implements Plugin { private isSidebarEnabled = true; public setup(core: CoreSetup, plugins: PluginsSetup) { - const { cloud } = plugins; const { config } = this; + if (!config.ui?.enabled) { + return; + } + const { cloud } = plugins; core.application.register({ appRoute: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, @@ -416,6 +419,9 @@ export class EnterpriseSearchPlugin implements Plugin { } public start(core: CoreStart) { + if (!this.config.ui?.enabled) { + return; + } // This must be called here in start() and not in `applications/index.tsx` to prevent loading // race conditions with our apps' `routes.ts` being initialized before `renderApp()` docLinks.setDocLinks(core.docLinks); diff --git a/x-pack/plugins/enterprise_search/server/api/connectors_service.ts b/x-pack/plugins/enterprise_search/server/api/connectors_service.ts new file mode 100644 index 0000000000000..f13f02cb50796 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/api/connectors_service.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IClusterClient } from '@kbn/core-elasticsearch-server'; +import { HttpServiceStart, KibanaRequest } from '@kbn/core-http-server'; + +import { CONNECTOR_DEFINITIONS } from '../../common/connectors/connectors'; + +import { Connector, IngestPipelineParams } from '../../common/types/connectors'; + +import { addConnector } from '../lib/connectors/add_connector'; +import { fetchConnectors } from '../lib/connectors/fetch_connectors'; + +export class ConnectorsService { + private readonly clusterClient: IClusterClient; + private readonly http: HttpServiceStart; + + constructor({ clusterClient, http }: { clusterClient: IClusterClient; http: HttpServiceStart }) { + this.clusterClient = clusterClient; + this.http = http; + } + + async createConnector( + request: KibanaRequest, + input: { + indexName: string | null; + isNative: boolean; + language: string | null; + pipeline?: IngestPipelineParams | null; + serviceType: string | null; + } + ): Promise { + return await addConnector(this.clusterClient.asScoped(request), input); + } + + getConnectorTypes() { + return CONNECTOR_DEFINITIONS.map((connector) => ({ + ...connector, + iconPath: connector.iconPath + ? this.http.basePath.prepend( + `/plugins/enterpriseSearch/assets/source_icons/${connector.iconPath}` + ) + : 'logoEnterpriseSearch', + })); + } + + async getConnectors(request: KibanaRequest): Promise { + return await fetchConnectors(this.clusterClient.asScoped(request)); + } +} diff --git a/x-pack/plugins/enterprise_search/server/index.ts b/x-pack/plugins/enterprise_search/server/index.ts index 120a8a231d6e8..e7df036ada1a4 100644 --- a/x-pack/plugins/enterprise_search/server/index.ts +++ b/x-pack/plugins/enterprise_search/server/index.ts @@ -8,7 +8,7 @@ import { schema, TypeOf } from '@kbn/config-schema'; import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; -import { EnterpriseSearchPlugin } from './plugin'; +import { EnterpriseSearchPlugin, EnterpriseSearchPluginStart as PluginStart } from './plugin'; export const plugin = (initializerContext: PluginInitializerContext) => { return new EnterpriseSearchPlugin(initializerContext); @@ -37,6 +37,9 @@ export const configSchema = schema.object({ { defaultValue: 'full' } ), }), + ui: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + }), }); export type ConfigType = TypeOf; @@ -45,6 +48,7 @@ export const config: PluginConfigDescriptor = { exposeToBrowser: { canDeployEntSearch: true, host: true, + ui: true, }, schema: configSchema, }; @@ -54,3 +58,5 @@ export const CONNECTORS_JOBS_INDEX = '.elastic-connectors-sync-jobs'; export const CURRENT_CONNECTORS_JOB_INDEX = '.elastic-connectors-sync-jobs-v1'; export const CONNECTORS_VERSION = 1; export const CRAWLERS_INDEX = '.ent-search-actastic-crawler2_configurations_v2'; + +export type EnterpriseSearchPluginStart = PluginStart; diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts index 5f9168bffe5e7..fe18dbccda2d8 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts @@ -64,11 +64,11 @@ describe('addConnector lib function', () => { await expect( addConnector(mockClient as unknown as IScopedClusterClient, { - index_name: 'index_name', - is_native: false, + indexName: 'index_name', + isNative: false, language: 'fr', }) - ).resolves.toEqual({ id: 'fakeId', index_name: 'index_name' }); + ).resolves.toEqual(expect.objectContaining({ id: 'fakeId', index_name: 'index_name' })); expect(mockClient.asCurrentUser.index).toHaveBeenCalledWith({ document: { api_key_id: null, @@ -175,8 +175,8 @@ describe('addConnector lib function', () => { await expect( addConnector(mockClient as unknown as IScopedClusterClient, { - index_name: 'index_name', - is_native: true, + indexName: 'index_name', + isNative: true, language: 'en', }) ).rejects.toEqual(new Error(ErrorCode.INDEX_ALREADY_EXISTS)); @@ -192,8 +192,8 @@ describe('addConnector lib function', () => { await expect( addConnector(mockClient as unknown as IScopedClusterClient, { - index_name: 'index_name', - is_native: false, + indexName: 'index_name', + isNative: false, language: 'en', }) ).rejects.toEqual(new Error(ErrorCode.CONNECTOR_DOCUMENT_ALREADY_EXISTS)); @@ -209,8 +209,8 @@ describe('addConnector lib function', () => { await expect( addConnector(mockClient as unknown as IScopedClusterClient, { - index_name: 'index_name', - is_native: false, + indexName: 'index_name', + isNative: false, language: 'en', }) ).rejects.toEqual(new Error(ErrorCode.CRAWLER_ALREADY_EXISTS)); @@ -226,8 +226,8 @@ describe('addConnector lib function', () => { await expect( addConnector(mockClient as unknown as IScopedClusterClient, { - index_name: 'index_name', - is_native: true, + indexName: 'index_name', + isNative: true, language: 'en', }) ).rejects.toEqual(new Error(ErrorCode.INDEX_ALREADY_EXISTS)); @@ -243,12 +243,12 @@ describe('addConnector lib function', () => { await expect( addConnector(mockClient as unknown as IScopedClusterClient, { - delete_existing_connector: true, - index_name: 'index_name', - is_native: true, + deleteExistingConnector: true, + indexName: 'index_name', + isNative: true, language: null, }) - ).resolves.toEqual({ id: 'fakeId', index_name: 'index_name' }); + ).resolves.toEqual(expect.objectContaining({ id: 'fakeId', index_name: 'index_name' })); expect(deleteConnectorById).toHaveBeenCalledWith(mockClient, 'connectorId'); expect(mockClient.asCurrentUser.index).toHaveBeenCalledWith({ document: { diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts index c3a7ebe26dc3f..891a3e14a2a62 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts @@ -8,7 +8,11 @@ import { IScopedClusterClient } from '@kbn/core/server'; import { CURRENT_CONNECTORS_INDEX } from '../..'; -import { ConnectorDocument } from '../../../common/types/connectors'; +import { + Connector, + ConnectorDocument, + IngestPipelineParams, +} from '../../../common/types/connectors'; import { ErrorCode } from '../../../common/types/error_codes'; import { createConnectorDocument } from '../../utils/create_connector_document'; @@ -25,58 +29,58 @@ const createConnector = async ( client: IScopedClusterClient, language: string | null, deleteExisting: boolean -): Promise<{ id: string; index_name: string }> => { +): Promise => { const index = document.index_name; - const indexExists = await client.asCurrentUser.indices.exists({ index }); - if (indexExists) { - { - throw new Error(ErrorCode.INDEX_ALREADY_EXISTS); + if (index) { + const indexExists = await client.asCurrentUser.indices.exists({ index }); + if (indexExists) { + { + throw new Error(ErrorCode.INDEX_ALREADY_EXISTS); + } } - } - const connector = await fetchConnectorByIndexName(client, index); - if (connector) { - if (deleteExisting) { - await deleteConnectorById(client, connector.id); - } else { - throw new Error(ErrorCode.CONNECTOR_DOCUMENT_ALREADY_EXISTS); + const connector = await fetchConnectorByIndexName(client, index); + if (connector) { + if (deleteExisting) { + await deleteConnectorById(client, connector.id); + } else { + throw new Error(ErrorCode.CONNECTOR_DOCUMENT_ALREADY_EXISTS); + } } - } - const crawler = await fetchCrawlerByIndexName(client, index); + const crawler = await fetchCrawlerByIndexName(client, index); - if (crawler) { - throw new Error(ErrorCode.CRAWLER_ALREADY_EXISTS); + if (crawler) { + throw new Error(ErrorCode.CRAWLER_ALREADY_EXISTS); + } + await createIndex(client, index, language, false); } - const result = await client.asCurrentUser.index({ document, index: CURRENT_CONNECTORS_INDEX, refresh: 'wait_for', }); - await createIndex(client, document.index_name, language, false); - return { id: result._id, index_name: document.index_name }; + return { ...document, id: result._id }; }; export const addConnector = async ( client: IScopedClusterClient, input: { - delete_existing_connector?: boolean; - index_name: string; - is_native: boolean; + deleteExistingConnector?: boolean; + indexName: string | null; + isNative: boolean; language: string | null; - service_type?: string; + pipeline?: IngestPipelineParams | null; + serviceType?: string | null; } -): Promise<{ id: string; index_name: string }> => { - const pipeline = await getDefaultPipeline(client); +): Promise => { + const pipeline = input.pipeline || (await getDefaultPipeline(client)); const document = createConnectorDocument({ - indexName: input.index_name, - isNative: input.is_native, - language: input.language, + ...input, pipeline, - serviceType: input.service_type ?? null, + serviceType: input.serviceType || null, }); - return await createConnector(document, client, input.language, !!input.delete_existing_connector); + return await createConnector(document, client, input.language, !!input.deleteExistingConnector); }; diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.ts index 4c9ce9ffc162f..faac79a29c0a7 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.ts @@ -23,6 +23,7 @@ import { TriggerMethod, } from '../../../common/types/connectors'; import { ErrorCode } from '../../../common/types/error_codes'; +import { stripSearchPrefix } from '../../../common/utils/strip_search_prefix'; export const startConnectorSync = async ( client: IScopedClusterClient, @@ -65,7 +66,7 @@ export const startConnectorSync = async ( }); } - const indexNameWithoutSearchPrefix = index_name.replace('search-', ''); + const indexNameWithoutSearchPrefix = index_name ? stripSearchPrefix(index_name) : ''; const targetIndexName = jobType === SyncJobType.ACCESS_CONTROL ? `${CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX}${indexNameWithoutSearchPrefix}` diff --git a/x-pack/plugins/enterprise_search/server/lib/crawler/fetch_crawler_multiple_schedules.ts b/x-pack/plugins/enterprise_search/server/lib/crawler/fetch_crawler_multiple_schedules.ts index efc17ea6915d8..666921a950a8c 100644 --- a/x-pack/plugins/enterprise_search/server/lib/crawler/fetch_crawler_multiple_schedules.ts +++ b/x-pack/plugins/enterprise_search/server/lib/crawler/fetch_crawler_multiple_schedules.ts @@ -24,3 +24,14 @@ export const fetchCrawlerCustomSchedulingByIndexName = async ( const result = crawlerResult.hits.hits[0]?._source; return result; }; + +export const fetchCrawlerCustomSchedulingKeysByIndexName = async ( + client: IScopedClusterClient, + indexName: string +): Promise => { + const crawlerCustomSchedules = await fetchCrawlerCustomSchedulingByIndexName(client, indexName); + + return crawlerCustomSchedules?.custom_scheduling + ? Object.keys(crawlerCustomSchedules.custom_scheduling) + : []; +}; diff --git a/x-pack/plugins/enterprise_search/server/lib/crawler/post_crawler_multiple_schedules.ts b/x-pack/plugins/enterprise_search/server/lib/crawler/post_crawler_multiple_schedules.ts index b05077e26821b..21d9f8b558800 100644 --- a/x-pack/plugins/enterprise_search/server/lib/crawler/post_crawler_multiple_schedules.ts +++ b/x-pack/plugins/enterprise_search/server/lib/crawler/post_crawler_multiple_schedules.ts @@ -15,6 +15,7 @@ import { CrawlerCustomScheduleServer, } from '../../../common/types/crawler'; +import { fetchCrawlerCustomSchedulingKeysByIndexName } from './fetch_crawler_multiple_schedules'; import { fetchCrawlerDocumentIdByIndexName } from './fetch_crawlers'; const convertCustomScheduleMappingClientToServer = ( @@ -64,12 +65,37 @@ export const postCrawlerCustomScheduling = async ( customSchedules: CrawlerCustomScheduleMappingClient ) => { const connectorId = await fetchCrawlerDocumentIdByIndexName(client, indexName); - const convertCustomSchedulesServer = convertCustomScheduleMappingClientToServer(customSchedules); + const customSchedulingPayload = convertCustomScheduleMappingClientToServer(customSchedules); + + const existingCustomScheduleKeys = await fetchCrawlerCustomSchedulingKeysByIndexName( + client, + indexName + ); + const newCustomScheduleKeys = Array.from(customSchedulingPayload.keys()); + const scheduleKeysToDelete = existingCustomScheduleKeys.filter( + (key) => !newCustomScheduleKeys.includes(key) + ); + + // Handle deleted schedules + if (scheduleKeysToDelete.length > 0) { + const scriptSource = scheduleKeysToDelete + .map((scheduleKey) => `ctx._source['custom_scheduling'].remove('${scheduleKey}');`) + .join(' '); + + await client.asCurrentUser.update({ + index: CONNECTORS_INDEX, + id: connectorId, + script: { + source: scriptSource, + }, + }); + } + return await client.asCurrentUser.update({ index: CONNECTORS_INDEX, id: connectorId, doc: { - custom_scheduling: Object.fromEntries(convertCustomSchedulesServer), + custom_scheduling: Object.fromEntries(customSchedulingPayload), }, }); }; diff --git a/x-pack/plugins/enterprise_search/server/lib/indices/delete_access_control_index.ts b/x-pack/plugins/enterprise_search/server/lib/indices/delete_access_control_index.ts index 8e4cba7351f69..1937df11b912c 100644 --- a/x-pack/plugins/enterprise_search/server/lib/indices/delete_access_control_index.ts +++ b/x-pack/plugins/enterprise_search/server/lib/indices/delete_access_control_index.ts @@ -8,12 +8,14 @@ import { IScopedClusterClient } from '@kbn/core/server'; import { CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX } from '../../../common/constants'; +import { stripSearchPrefix } from '../../../common/utils/strip_search_prefix'; + import { isIndexNotFoundException } from '../../utils/identify_exceptions'; export const deleteAccessControlIndex = async (client: IScopedClusterClient, index: string) => { try { return await client.asCurrentUser.indices.delete({ - index: index.replace('search-', CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX), + index: stripSearchPrefix(index, CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX), }); } catch (e) { // Gracefully exit if index not found. This is a valid case. diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts index 041a295ff4831..ed6ef8f3886bf 100644 --- a/x-pack/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/plugins/enterprise_search/server/plugin.ts @@ -15,6 +15,8 @@ import { IRouter, KibanaRequest, DEFAULT_APP_CATEGORIES, + IClusterClient, + CoreStart, } from '@kbn/core/server'; import { CustomIntegrationsPluginSetup } from '@kbn/custom-integrations-plugin/server'; import { DataPluginStart } from '@kbn/data-plugin/server/plugin'; @@ -49,6 +51,7 @@ import { databaseSearchGuideConfig, } from '../common/guided_onboarding/search_guide_config'; +import { ConnectorsService } from './api/connectors_service'; import { registerTelemetryUsageCollector as registerASTelemetryUsageCollector } from './collectors/app_search/telemetry'; import { registerTelemetryUsageCollector as registerESTelemetryUsageCollector } from './collectors/enterprise_search/telemetry'; import { registerTelemetryUsageCollector as registerWSTelemetryUsageCollector } from './collectors/workplace_search/telemetry'; @@ -100,6 +103,10 @@ interface PluginsStart { spaces?: SpacesPluginStart; } +export interface EnterpriseSearchPluginStart { + connectorsService: ConnectorsService; +} + export interface RouteDependencies { config: ConfigType; enterpriseSearchRequestHandler: IEnterpriseSearchRequestHandler; @@ -109,9 +116,14 @@ export interface RouteDependencies { router: IRouter; } -export class EnterpriseSearchPlugin implements Plugin { +export class EnterpriseSearchPlugin implements Plugin { private readonly config: ConfigType; private readonly logger: Logger; + private clusterClient?: IClusterClient; + /** + * Exposed services + */ + private connectorsService?: ConnectorsService; constructor(initializerContext: PluginInitializerContext) { this.config = initializerContext.config.get(); @@ -191,7 +203,7 @@ export class EnterpriseSearchPlugin implements Plugin { enterpriseSearchApplications: showEnterpriseSearch, enterpriseSearchEsre: showEnterpriseSearch, enterpriseSearchVectorSearch: showEnterpriseSearch, - elasticsearch: showEnterpriseSearch, + enterpriseSearchElasticsearch: showEnterpriseSearch, appSearch: hasAppSearchAccess && config.canDeployEntSearch, workplaceSearch: hasWorkplaceSearchAccess && config.canDeployEntSearch, searchExperiences: showEnterpriseSearch, @@ -203,7 +215,7 @@ export class EnterpriseSearchPlugin implements Plugin { enterpriseSearchApplications: showEnterpriseSearch, enterpriseSearchEsre: showEnterpriseSearch, enterpriseSearchVectorSearch: showEnterpriseSearch, - elasticsearch: showEnterpriseSearch, + enterpriseSearchElasticsearch: showEnterpriseSearch, appSearch: hasAppSearchAccess && config.canDeployEntSearch, workplaceSearch: hasWorkplaceSearchAccess && config.canDeployEntSearch, searchExperiences: showEnterpriseSearch, @@ -247,6 +259,7 @@ export class EnterpriseSearchPlugin implements Plugin { let savedObjectsStarted: SavedObjectsServiceStart; getStartServices().then(([coreStart]) => { + this.clusterClient = coreStart.elasticsearch.client; savedObjectsStarted = coreStart.savedObjects; if (usageCollection) { @@ -309,7 +322,26 @@ export class EnterpriseSearchPlugin implements Plugin { } } - public start() {} + public start(core: CoreStart) { + /** + * Create exposed plugin services + */ + if (!this.clusterClient) { + this.clusterClient = core.elasticsearch.client; + } + if (!this.connectorsService) { + this.connectorsService = new ConnectorsService({ + clusterClient: this.clusterClient, + http: core.http, + }); + } + if (!this.connectorsService) { + this.logger.warn('Enterprise Search connectors service has not been initialized'); + } + return Object.freeze({ + connectorsService: this.connectorsService, + }); + } public stop() {} } diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts index 1cac51b7456cd..923009c05d098 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts @@ -56,7 +56,13 @@ export function registerConnectorRoutes({ router, log }: RouteDependencies) { elasticsearchErrorHandler(log, async (context, request, response) => { const { client } = (await context.core).elasticsearch; try { - const body = await addConnector(client, request.body); + const body = await addConnector(client, { + deleteExistingConnector: request.body.delete_existing_connector, + indexName: request.body.index_name, + isNative: request.body.is_native, + language: request.body.language, + serviceType: request.body.service_type, + }); return response.ok({ body }); } catch (error) { if ( diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts index 9e4ff21888e5e..c5c45806e560f 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts @@ -43,11 +43,11 @@ export function registerCrawlerRoutes(routeDependencies: RouteDependencies) { }, elasticsearchErrorHandler(log, async (context, request, response) => { const connParams = { - delete_existing_connector: true, - index_name: request.body.index_name, - is_native: true, + deleteExistingConnector: true, + indexName: request.body.index_name, + isNative: true, language: request.body.language, - service_type: ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE, + serviceType: ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE, }; const { client } = (await context.core).elasticsearch; @@ -113,7 +113,9 @@ export function registerCrawlerRoutes(routeDependencies: RouteDependencies) { const createdConnector = await fetchConnectorByIndexName(client, request.body.index_name); if (createdConnector) { await deleteConnectorById(client, createdConnector.id); - await deleteIndex(client, createdConnector.index_name); + if (createdConnector.index_name) { + await deleteIndex(client, createdConnector.index_name); + } } throw error; diff --git a/x-pack/plugins/enterprise_search/server/utils/create_connector_document.ts b/x-pack/plugins/enterprise_search/server/utils/create_connector_document.ts index 27a7ad5d9340c..8b3883eac5be9 100644 --- a/x-pack/plugins/enterprise_search/server/utils/create_connector_document.ts +++ b/x-pack/plugins/enterprise_search/server/utils/create_connector_document.ts @@ -16,17 +16,20 @@ import { FilteringValidationState, IngestPipelineParams, } from '../../common/types/connectors'; +import { stripSearchPrefix } from '../../common/utils/strip_search_prefix'; export function createConnectorDocument({ indexName, isNative, + name, pipeline, serviceType, language, }: { - indexName: string; + indexName: string | null; isNative: boolean; language: string | null; + name?: string; pipeline?: IngestPipelineParams | null; serviceType: string | null; }): ConnectorDocument { @@ -123,7 +126,7 @@ export function createConnectorDocument({ last_sync_scheduled_at: null, last_sync_status: null, last_synced: null, - name: indexName.startsWith('search-') ? indexName.substring(7) : indexName, + name: name || stripSearchPrefix(indexName ?? ''), pipeline, scheduling: { access_control: { enabled: false, interval: '0 0 0 * * ?' }, diff --git a/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts b/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts index 13ead48887acb..0869a16b79dc7 100644 --- a/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts +++ b/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts @@ -98,32 +98,34 @@ export function getSearchResultProvider( ] : []), ...(config.hasConnectors ? CONNECTOR_DEFINITIONS : []), - ...[ - { - keywords: ['app', 'search', 'engines'], - name: i18n.translate('xpack.enterpriseSearch.searchProvider.appSearch.name', { - defaultMessage: 'App Search', - }), - serviceType: 'app_search', - url: APP_SEARCH_PLUGIN.URL, - }, - { - keywords: ['workplace', 'search'], - name: i18n.translate('xpack.enterpriseSearch.searchProvider.workplaceSearch.name', { - defaultMessage: 'Workplace Search', - }), - serviceType: 'workplace_search', - url: WORKPLACE_SEARCH_PLUGIN.URL, - }, - { - keywords: ['esre', 'search'], - name: i18n.translate('xpack.enterpriseSearch.searchProvider.esre.name', { - defaultMessage: 'ESRE', - }), - serviceType: 'esre', - url: ESRE_PLUGIN.URL, - }, - ], + ...(config.canDeployEntSearch + ? [ + { + keywords: ['app', 'search', 'engines'], + name: i18n.translate('xpack.enterpriseSearch.searchProvider.appSearch.name', { + defaultMessage: 'App Search', + }), + serviceType: 'app_search', + url: APP_SEARCH_PLUGIN.URL, + }, + { + keywords: ['workplace', 'search'], + name: i18n.translate('xpack.enterpriseSearch.searchProvider.workplaceSearch.name', { + defaultMessage: 'Workplace Search', + }), + serviceType: 'workplace_search', + url: WORKPLACE_SEARCH_PLUGIN.URL, + }, + { + keywords: ['esre', 'search'], + name: i18n.translate('xpack.enterpriseSearch.searchProvider.esre.name', { + defaultMessage: 'ESRE', + }), + serviceType: 'esre', + url: ESRE_PLUGIN.URL, + }, + ] + : []), ]; const result = services .map((service) => { 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/cluster_client_adapter.test.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts index 6f36af2be1f78..e51108c6e701d 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts @@ -168,38 +168,17 @@ describe('buffering documents', () => { describe('doesIndexTemplateExist', () => { test('should call cluster with proper arguments', async () => { await clusterClientAdapter.doesIndexTemplateExist('foo'); - expect(clusterClient.indices.existsTemplate).toHaveBeenCalledWith({ + expect(clusterClient.indices.existsIndexTemplate).toHaveBeenCalledWith({ name: 'foo', }); }); - test('should return true when call cluster to legacy template API returns true', async () => { - clusterClient.indices.existsTemplate.mockResponse(true); - clusterClient.indices.existsIndexTemplate.mockResponse(false); - await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(true); - }); - test('should return true when call cluster to index template API returns true', async () => { clusterClient.indices.existsTemplate.mockResponse(false); clusterClient.indices.existsIndexTemplate.mockResponse(true); await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(true); }); - test('should return false when both call cluster calls returns false', async () => { - clusterClient.indices.existsTemplate.mockResponse(false); - clusterClient.indices.existsIndexTemplate.mockResponse(false); - await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(false); - }); - - test('should throw error when call cluster to legacy template API throws an error', async () => { - clusterClient.indices.existsTemplate.mockRejectedValue(new Error('Fail')); - await expect( - clusterClientAdapter.doesIndexTemplateExist('foo') - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"error checking existence of index template: Fail"` - ); - }); - test('should throw error when call cluster to index template API throws an error', async () => { clusterClient.indices.existsIndexTemplate.mockRejectedValue(new Error('Fail')); await expect( diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts index 27a86b839d6c9..1eb1219621c37 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts @@ -181,9 +181,8 @@ export class ClusterClientAdapter { try { const esClient = await this.elasticsearchClientPromise; - const legacyResult = await esClient.indices.existsTemplate({ name }); const indexTemplateResult = await esClient.indices.existsIndexTemplate({ name }); - return (legacyResult as boolean) || (indexTemplateResult as boolean); + return indexTemplateResult as boolean; } catch (err) { throw new Error(`error checking existence of index template: ${err.message}`); } 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/.storybook/context/index.tsx b/x-pack/plugins/fleet/.storybook/context/index.tsx index cd89848008f98..43d3eea74df33 100644 --- a/x-pack/plugins/fleet/.storybook/context/index.tsx +++ b/x-pack/plugins/fleet/.storybook/context/index.tsx @@ -16,6 +16,8 @@ import { I18nProvider } from '@kbn/i18n-react'; import { CoreScopedHistory } from '@kbn/core/public'; import { getStorybookContextProvider } from '@kbn/custom-integrations-plugin/storybook'; +import type { DashboardStart } from '@kbn/dashboard-plugin/public'; + import { IntegrationsAppContext } from '../../public/applications/integrations/app'; import type { FleetConfigType, FleetStartServices } from '../../public/plugin'; import { ExperimentalFeaturesService } from '../../public/services'; @@ -76,6 +78,7 @@ export const StorybookContext: React.FC<{ storyContext?: Parameters languageClientsUiComponents: {}, }, customBranding: getCustomBranding(), + dashboard: {} as unknown as DashboardStart, docLinks: getDocLinks(), http: getHttp(), i18n: { diff --git a/x-pack/plugins/fleet/common/experimental_features.ts b/x-pack/plugins/fleet/common/experimental_features.ts index cfdb8cf5fd26b..39d7b998953fb 100644 --- a/x-pack/plugins/fleet/common/experimental_features.ts +++ b/x-pack/plugins/fleet/common/experimental_features.ts @@ -46,6 +46,7 @@ export const parseExperimentalConfigValue = (configValue: string[]): Experimenta throw new FleetInvalidExperimentalValue(`[${value}] is not a supported experimental feature`); } + // @ts-expect-error ts upgrade v4.7.4 enabledFeatures[value as keyof ExperimentalFeatures] = true; } diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index 4268bcca3b042..919d67392770d 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -13,6 +13,8 @@ import type { Output } from './output'; export type AgentPolicyStatus = typeof agentPolicyStatuses; +// adding a property here? If it should be cloned when duplicating a policy, add it to `agentPolicyService.copy` +// x-pack/plugins/fleet/server/services/agent_policy.ts#L571 export interface NewAgentPolicy { id?: string; name: string; 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/kibana.jsonc b/x-pack/plugins/fleet/kibana.jsonc index f0b01080db22d..b9f892ba4809d 100644 --- a/x-pack/plugins/fleet/kibana.jsonc +++ b/x-pack/plugins/fleet/kibana.jsonc @@ -23,7 +23,8 @@ "taskManager", "guidedOnboarding", "files", - "uiActions" + "uiActions", + "dashboard" ], "optionalPlugins": [ "features", 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/components/fleet_server_instructions/utils/install_command_utils.ts b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/utils/install_command_utils.ts index b528c5092ea14..ff69a3b4f5edd 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/utils/install_command_utils.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/utils/install_command_utils.ts @@ -52,9 +52,6 @@ function getArtifact(platform: PLATFORM_TYPE, kibanaVersion: string) { kubernetes: { downloadCommand: '', }, - googleCloudShell: { - downloadCommand: '', - }, }; return artifactMap[platform]; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.test.tsx index fe21159ab347b..ceea82434e1e1 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.test.tsx @@ -54,6 +54,7 @@ describe('Agent policy advanced options content', () => { // remove when feature flag is removed ExperimentalFeaturesService.init({ ...allowedExperimentalValues, + // @ts-expect-error ts upgrade v4.7.4 agentTamperProtectionEnabled: true, }); 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 ? ( { // todo: this can be removed when agentTamperProtectionEnabled feature flag is enabled/deleted ExperimentalFeaturesService.init({ ...allowedExperimentalValues, + // @ts-expect-error ts upgrade v4.7.4 agentTamperProtectionEnabled: true, }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_list_table.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_list_table.tsx index 294b3a69644c4..8709d0fc9adcf 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_list_table.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_list_table.tsx @@ -180,9 +180,11 @@ export const AgentListTable: React.FC = (props: Props) => { const showWarning = agent.policy_revision && agentPolicy?.revision > agent.policy_revision; return ( - + {agentPolicy && ( - + + + )} {showWarning && ( @@ -191,7 +193,7 @@ export const AgentListTable: React.FC = (props: Props) => {   diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx index e42dfd997d241..25c394e2606b0 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx @@ -5,13 +5,37 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DASHBOARD_LOCATORS_IDS } from '../../../../../../../common/constants'; -import { useDashboardLocator } from '../../../../hooks'; +import { useDashboardLocator, useStartServices } from '../../../../hooks'; + +const useDashboardExists = (dashboardId: string) => { + const [dashboardExists, setDashboardExists] = React.useState(false); + const [loading, setLoading] = React.useState(true); + const { dashboard: dashboardPlugin } = useStartServices(); + + useEffect(() => { + const fetchDashboard = async () => { + try { + const findDashboardsService = await dashboardPlugin.findDashboardsService(); + const [dashboard] = await findDashboardsService.findByIds([dashboardId]); + setLoading(false); + setDashboardExists(dashboard?.status === 'success'); + } catch (e) { + setLoading(false); + setDashboardExists(false); + } + }; + + fetchDashboard(); + }, [dashboardId, dashboardPlugin]); + + return { dashboardExists, loading }; +}; export const DashboardsButtons: React.FunctionComponent = () => { const dashboardLocator = useDashboardLocator(); @@ -20,6 +44,14 @@ export const DashboardsButtons: React.FunctionComponent = () => { return dashboardLocator?.getRedirectUrl({ dashboardId }) || ''; }; + const { dashboardExists, loading: dashboardLoading } = useDashboardExists( + DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_OVERVIEW + ); + + if (dashboardLoading || !dashboardExists) { + return null; + } + return ( <> diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx index 437f982bed706..27b62d54bd789 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx @@ -22,6 +22,8 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import styled from 'styled-components'; +import { useIsFirstTimeAgentUserQuery } from '../../../../../integrations/sections/epm/screens/detail/hooks'; + import type { Agent, AgentPolicy } from '../../../../types'; import { SearchBar } from '../../../../components'; import { AGENTS_INDEX, AGENTS_PREFIX } from '../../../../constants'; @@ -94,6 +96,8 @@ export const SearchAndFilterBar: React.FunctionComponent { const { euiTheme } = useEuiTheme(); const { isFleetServerStandalone } = useFleetServerStandalone(); + const { isFirstTimeAgentUser, isLoading: isFirstTimeAgentUserLoading } = + useIsFirstTimeAgentUserQuery(); const showAddFleetServerBtn = !isFleetServerStandalone; // Policies state for filtering @@ -126,7 +130,9 @@ export const SearchAndFilterBar: React.FunctionComponent {/* Top Buttons and Links */} - {totalAgents > 0 && } + + {!isFirstTimeAgentUserLoading && !isFirstTimeAgentUser && } + { // todo: this can be removed when agentTamperProtectionEnabled feature flag is enabled/deleted ExperimentalFeaturesService.init({ ...allowedExperimentalValues, + // @ts-expect-error ts upgrade v4.7.4 agentTamperProtectionEnabled: true, }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_kafka_partitioning.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_kafka_partitioning.tsx index c2695660aa52a..6acb44fe33af5 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_kafka_partitioning.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_kafka_partitioning.tsx @@ -55,6 +55,7 @@ export const OutputFormKafkaPartitioning: React.FunctionComponent<{ defaultMessage="Number of events" /> } + {...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}